Clan x86

Technical (Development, Security, etc.) => General Programming => Tutorials, References, and Examples => Topic started by: Camel on September 23, 2007, 05:56:31 PM

Title: [Java] ChatQueue
Post by: Camel on September 23, 2007, 05:56:31 PM
Here's the ChatQueue class from my bot. If flood protection (boolean fp) is enabled, enqueue() will throw the string in a linked list, and the thread will come around and pick a Connection to send the text on. If fp is disabled, then it will send text immediately in round-robin order.

http://bnubot.googlecode.com/svn/trunk/BNUBot/src/net/bnubot/core/ChatQueue.java
/**
* This file is distributed under the GPL
* $Id$
*/

package net.bnubot.core;

import java.util.Iterator;
import java.util.LinkedList;


public class ChatQueue extends Thread {
   private LinkedList<Connection> cons = new LinkedList<Connection>();
   private LinkedList<String> queue = new LinkedList<String>();
   private int lastCon = 0;
   
   public ChatQueue() {
      super(ChatQueue.class.getSimpleName());
      setDaemon(true);
   }
   
   public boolean add(Connection c) {
      synchronized(cons) {
         return cons.add(c);
      }
   }
   
   public boolean enqueue(String text, boolean fp) {
      if(fp) synchronized(queue) {
         return queue.add(text);
      }
      if(lastCon >= cons.size())
         lastCon = 0;
      cons.get(lastCon++).sendChatNow(text);
      return true;
   }
   
   public void run() {
      //TODO: flag condition for when there's a /kick or /ban but no ops are connected
      while(true) {
         // If there's text in the queue to send
         if(queue.size() > 0) {
            // Iterate through the connecitons
            Iterator<Connection> it = cons.iterator();
            while(it.hasNext()) {
               Connection con = it.next();
               // Check if the con can send text now
               if(con.canSendChat()) {
                  if(!con.isOp()) {
                     //Find a string we can send
                     int queueIndex;
                     findSendableText: for(queueIndex = 0; queueIndex < queue.size(); queueIndex++) {
                        String text = queue.get(queueIndex);
                        
                        // Check if ops is required
                        try {
                           if(text.charAt(0) == '/') {
                              String cmd = text.substring(1);
                              int i = cmd.indexOf(' ');
                              if(i != -1) {
                                 cmd = cmd.substring(0, i).toLowerCase();
                                 
                                 if(cmd.equals("kick")
                                 || cmd.equals("ban"))
                                    continue findSendableText;
                              }
                           }
                        } catch(Exception e) {}

                        // Write the text out
                        con.sendChatNow(queue.remove(queueIndex));
                     }
                  } else {
                     // Write the text out
                     con.sendChatNow(queue.remove());
                  }
                  
                  // If the queue is empty, stop
                  if(queue.size() == 0)
                     break;
               }
            }
            
         }
         
         yield();
         try { sleep(10); } catch(Exception e) {}
      }
   }
}
Title: Re: [Java] ChatQueue
Post by: iago on September 24, 2007, 10:44:50 AM
Quote from: Camel on September 23, 2007, 05:56:31 PM

         try { sleep(10); } catch(Exception e) {}

One of my least favorite things that Java forces you to do. Damn Java!
Title: Re: [Java] ChatQueue
Post by: Camel on September 24, 2007, 12:12:01 PM
Agreed; it's nice that it informs you whether it succeeded, but it could accomplish the same by returning a boolean. The way I see it, exceptions have two purposes: to provide details about the error, and to provide a stack trace. Since InterruptedExceptions or whatever they're using are not useful for either case, they shouldn't exist.
Title: Re: [Java] ChatQueue
Post by: Chavo on September 24, 2007, 05:13:44 PM
a boolean wouldn't be as useful in the case that you have another thread waking your sleeping thread and want to send a message or control (it could be necessary to differentiate between a timeout and a forced wakeup)
Title: Re: [Java] ChatQueue
Post by: Camel on September 24, 2007, 07:25:18 PM
Quote from: Chavo on September 24, 2007, 05:13:44 PM
a boolean wouldn't be as useful in the case that you have another thread waking your sleeping thread and want to send a message or control (it could be necessary to differentiate between a timeout and a forced wakeup)

Booleans have two states: true, and false.

There are only two conditions for sleep() to stop blocking: timeout, and forced wakeup.

What's confusing about that?
Title: Re: [Java] ChatQueue
Post by: Chavo on September 24, 2007, 10:17:17 PM
Two conditions aren't sufficient to describe all possible circumstances that might cause a thread to wakeup.  If true is a normal timeout return and false describes any unintended interrupt, you would have to do significant extra work to find out what caused the unintended interrupt.  What's wrong with throwing an exception to find the cause of an error/non-timeout interrupt?

Don't get me wrong, I'm not a big fan of the syntax either but I can't think of anything better :)
Title: Re: [Java] ChatQueue
Post by: Camel on September 24, 2007, 11:41:06 PM
I can't think of any condition where the program should care why sleep() failed.
Title: Re: [Java] ChatQueue
Post by: iago on September 25, 2007, 10:06:16 AM
Quote from: Camel on September 24, 2007, 11:41:06 PM
I can't think of any condition where the program should care why sleep() failed.
I can see rare reasons why it might care, but it can be handled on a case-by-case basis depending on what needs to happen.