Changeset 5975 for branches/newapi

Show
Ignore:
Timestamp:
01/01/08 20:28:13 (11 months ago)
Author:
erijo
Message:

Simplified EventQueue?

Refactored EventQueue? into a simple queue with push/pop instead of
pushEvent/getEvent/commitEvent. The commit logic is no longer in
EventQueue?, but in some other place (yet to be decided).

Location:
branches/newapi/licq
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • branches/newapi/licq/licq/event/eventqueue.h

    r5952 r5975  
    11/* 
    22 * This file is part of Licq, an instant messaging client for UNIX. 
    3  * Copyright (C) 2007 Erik Johansson <erijo@licq.org> 
     3 * Copyright (C) 2007-2008 Erik Johansson <erijo@licq.org> 
    44 * 
    55 * Licq is free software; you can redistribute it and/or modify 
     
    2828{ 
    2929 
     30/** 
     31 * EventQueue is a thread-safe producer-consumer queue. The 
     32 * producer(s) pushes events to the queue with push(). The consumer 
     33 * notices that the file descriptor returned from getFileDescriptor() 
     34 * is ready for reading and reads one or more bytes. For each byte 
     35 * read, it calls pop(), handles the event, and then passes the event 
     36 * on. 
     37 * 
     38 * @threadsafe 
     39 */ 
    3040class EventQueue : private boost::noncopyable 
    3141{ 
     
    3646   * be available for reading. 
    3747   * 
    38    * @returns The read file descriptor. 
     48   * @returns The read file descriptor, configured to be non-blocking. 
    3949   */ 
    4050  virtual int getFileDescriptor() const = 0; 
     
    4656 
    4757  /** 
    48    * Pushes an event to the end of the queue. The queue takes 
    49    * ownership of the event and @a event is reset before the function 
    50    * returns. 
     58   * Pushes an event to the end of the queue. Once an event has been 
     59   * pushed to the queue, it should not be used again by the caller, 
     60   * since another thread may already be using it. 
     61   * 
     62   * @param event The event to add to the queue. 
    5163   */ 
    52   virtual void pushEvent(boost::shared_ptr<Event>& event) = 0; 
     64  virtual void push(boost::shared_ptr<Event> event) = 0; 
    5365 
    5466  /** 
    55    * @returns The event in the front of the queue. 
     67   * Removes the first event from the queue and returns it. 
     68   * 
     69   * @returns The first event in the queue. 
    5670   * @throws Licq::RuntimeException If the queue is empty. 
    5771   */ 
    58   virtual boost::shared_ptr<Event> getEvent() const = 0; 
    59  
    60   /** 
    61    * Commit the event in front of the queue. Before committing, make 
    62    * sure that no reference to any Event returned from getEvent() 
    63    * remains. This may include calling boost::shared_ptr::reset(). 
    64    * 
    65    * @throws Licq::RuntimeException If the queue is empty. 
    66    */ 
    67   virtual void commitEvent() = 0; 
     72  virtual boost::shared_ptr<Event> pop() = 0; 
    6873 
    6974protected: 
  • branches/newapi/licq/src/event/eventqueue.cpp

    r5952 r5975  
    2525#include <cassert> 
    2626 
    27 LicqDaemon::EventQueue::EventQueue(const std::string& name, EventManager* manager) 
     27LicqDaemon::EventQueue::EventQueue(const std::string& name) 
    2828  : myName(name), 
    29     myEventManager(manager), 
    3029    myQueueMutex(name), 
    3130    myPipe(name) 
    3231{ 
    33   assert(myEventManager != NULL); 
    34  
    3532  myPipe.setBlockingRead(false); 
    3633  myPipe.setBlockingWrite(true); 
     
    3936LicqDaemon::EventQueue::~EventQueue() 
    4037{ 
    41   Licq::MutexLocker locker(&myQueueMutex); 
    42   while (!myQueue.empty()) 
    43     commitEventInternal(); 
     38  assert(empty()); 
    4439} 
    4540 
     
    5550} 
    5651 
    57 void LicqDaemon::EventQueue::pushEvent(boost::shared_ptr<Licq::Event>& event) 
     52void LicqDaemon::EventQueue::push(boost::shared_ptr<Licq::Event> event) 
    5853{ 
    59   // Take ownership of event 
    60   boost::shared_ptr<Licq::Event> newEvent; 
    61   newEvent.swap(event); 
    62   assert(newEvent.unique()); 
    63  
    6454  // Add to queue 
    6555  Licq::MutexLocker locker(&myQueueMutex); 
    66   myQueue.push(newEvent); 
     56  myQueue.push(event); 
    6757 
    6858  // Notify 
     
    7060} 
    7161 
    72 boost::shared_ptr<Licq::Event> LicqDaemon::EventQueue::getEvent() const 
     62boost::shared_ptr<Licq::Event> LicqDaemon::EventQueue::pop() 
    7363{ 
    7464  Licq::MutexLocker locker(&myQueueMutex); 
     
    7666    throw Licq::RuntimeException(tr("EventQueue %1% is empty") % myName); 
    7767 
    78   return myQueue.front(); 
    79 } 
    80  
    81 void LicqDaemon::EventQueue::commitEvent() 
    82 { 
    83   Licq::MutexLocker locker(&myQueueMutex); 
    84   if (myQueue.empty()) 
    85     throw Licq::RuntimeException(tr("EventQueue %1% is empty") % myName); 
    86  
    87   commitEventInternal(); 
    88 } 
    89  
    90 void LicqDaemon::EventQueue::commitEventInternal() 
    91 { 
    9268  boost::shared_ptr<Licq::Event> event = myQueue.front(); 
    9369  myQueue.pop(); 
    94  
    95   myEventManager->sendEvent(event); 
     70  return event; 
    9671} 
  • branches/newapi/licq/src/event/eventqueue.h

    r5952 r5975  
    2323#include "licq/event/eventqueue.h" 
    2424#include "licq/thread/mutex.h" 
    25 #include "event/eventmanager.h" 
    2625#include "util/pipe.h" 
    2726 
     
    3433{ 
    3534public: 
    36   EventQueue(const std::string& name, EventManager* manager); 
     35  EventQueue(const std::string& name); 
    3736  ~EventQueue(); 
    3837 
    3938  // From Licq::EventQueue 
    4039  int getFileDescriptor() const; 
    41   void pushEvent(boost::shared_ptr<Licq::Event>& event); 
    4240  bool empty() const; 
    43   boost::shared_ptr<Licq::Event> getEvent() const; 
    44   void commitEvent(); 
     41  void push(boost::shared_ptr<Licq::Event> event); 
     42  boost::shared_ptr<Licq::Event> pop(); 
    4543 
    4644private: 
    47   void commitEventInternal(); 
     45  typedef std::queue< boost::shared_ptr<Licq::Event> > Queue; 
     46  Queue myQueue; 
    4847 
    4948  const std::string myName; 
    50   EventManager* myEventManager; 
    51  
    52   typedef std::queue< boost::shared_ptr<Licq::Event> > Queue; 
    53   Queue myQueue; 
    5449  mutable Licq::Mutex myQueueMutex; 
    55  
    5650  Pipe myPipe; 
    5751}; 
  • branches/newapi/licq/src/event/test/eventqueuetest.cpp

    r5952 r5975  
    1818 */ 
    1919 
    20 #include "event/eventmanager.h" 
    2120#include "event/eventqueue.h" 
    22 #include "test/recorder.h" 
     21#include "licq/exception/runtimeexception.h" 
    2322 
    2423#include <boost/test/unit_test.hpp> 
    25 #include <cassert> 
    2624 
    27 struct EventQueueFixture : public LicqDaemon::EventManager 
     25struct EventQueueFixture 
    2826{ 
    29   void reset() 
     27  ssize_t read(Licq::EventQueue* queue) 
    3028  { 
    31     BOOST_REQUIRE(recorder.isEmpty()); 
     29    int fd = queue->getFileDescriptor(); 
     30 
     31    char buffer[16]; 
     32    return ::read(fd, &buffer, sizeof(buffer)); 
    3233  } 
    33  
    34   // EventManager 
    35   void registerQueue(const std::string&, Licq::EventQueue*, int) 
    36   { 
    37     assert(false); 
    38   } 
    39  
    40   void unregisterQueue(const std::string&, Licq::EventQueue*) 
    41   { 
    42     assert(false); 
    43   } 
    44  
    45   void unregisterQueue(Licq::EventQueue*) 
    46   { 
    47     assert(false); 
    48   } 
    49  
    50   void sendEvent(boost::shared_ptr<Licq::Event>& event) 
    51   { 
    52     recorder.push(boost::format("sendEvent(%1%)") % event->getId()); 
    53   } 
    54  
    55   LicqTest::Recorder recorder; 
    5634}; 
    5735 
     
    6038BOOST_AUTO_TEST_CASE(basic) 
    6139{ 
    62   reset(); 
     40  const size_t count = 5; 
     41  boost::shared_ptr<Licq::Event> event[count]; 
     42  Licq::Event::Id id[count]; 
    6343 
    64   LicqDaemon::EventQueue queue("test", this); 
    65   boost::shared_ptr<Licq::Event> test = Licq::Event::create("test"); 
    66   Licq::Event* testPtr = test.get(); 
    67   Licq::Event::Id id = test->getId(); 
     44  // Setup some events 
     45  for (size_t i = 0; i < count; i++) 
     46  { 
     47    event[i] = Licq::Event::create("test"); 
     48    id[i] = event[i]->getId(); 
     49    event[i]->setProperty("42 * i", (int)(42 * i)); 
     50  } 
    6851 
    69   queue.pushEvent(test); 
    70   BOOST_CHECK_EQUAL(queue.empty(), false); 
     52  boost::shared_ptr<Licq::Event> temp; 
    7153 
    72   // Adding an event should invalidate the pointer 
    73   BOOST_CHECK_EQUAL(test.get(), (Licq::Event*)NULL); 
     54  LicqDaemon::EventQueue queue("testqueue"); 
     55  BOOST_CHECK(queue.empty()); 
    7456 
    75   BOOST_CHECK_EQUAL(queue.getEvent().get(), testPtr); 
    76   queue.commitEvent(); 
    77   BOOST_CHECK_EQUAL(queue.empty(), true); 
     57  queue.push(event[0]); 
     58  BOOST_CHECK(!queue.empty()); 
     59  BOOST_CHECK_EQUAL(read(&queue), 1); 
    7860 
    79   BOOST_CHECK(recorder.pop(boost::format("sendEvent(%1%)") % id)); 
    80   BOOST_CHECK(recorder.isEmpty()); 
     61  // pop() should not leave the event in the queue 
     62  temp = queue.pop(); 
     63  BOOST_CHECK_EQUAL(temp, event[0]); 
     64  BOOST_CHECK_EQUAL(temp.use_count(), 2); 
     65 
     66  // Push events in order 
     67  for (size_t i = 0; i < count; i++) 
     68    queue.push(event[i]); 
     69 
     70  BOOST_CHECK_EQUAL(read(&queue), count); 
     71 
     72  // The queue should maintain order 
     73  for (size_t i = 0; i < count; i++) 
     74  { 
     75    temp = queue.pop(); 
     76    BOOST_CHECK_EQUAL(temp, event[i]); 
     77    BOOST_CHECK_EQUAL(temp->getId(), id[i]); 
     78    BOOST_CHECK_EQUAL(temp->getProperty<int>("42 * i"), (int)(42 * i)); 
     79  } 
     80 
     81  BOOST_CHECK(queue.empty()); 
     82  BOOST_CHECK_THROW(queue.pop(), Licq::RuntimeException); 
    8183} 
    8284 
  • branches/newapi/licq/src/plugin/plugininstanceimpl.cpp

    r5952 r5975  
    9494 
    9595  // Create the plugin's event queue 
    96   mySetup.eventQueue = new EventQueue(myInformation->name, 
    97                                       Globals::getEventManager()); 
     96  mySetup.eventQueue = new EventQueue(myInformation->name); 
    9897 
    9998  // Create the plugin 
  • branches/newapi/licq/src/plugin/pluginmanagerimpl.cpp

    r5931 r5975  
    6868  // Send started event 
    6969  boost::shared_ptr<Licq::Event> started = Licq::Event::create("started"); 
    70   instance->getEventQueue()->pushEvent(started); 
     70  instance->getEventQueue()->push(started); 
    7171 
    7272  return id;