00001 // $Id: mailbox.h,v 1.8 2008/12/21 09:40:47 dvermeir Exp $ 00002 #ifndef DV_THREAD_MAILBOX_H 00003 #define DV_THREAD_MAILBOX_H 00004 00005 #include <deque> 00006 #include <dvutil/convert.h> 00007 #include <dvthread/lock.h> 00008 00009 namespace Dv { 00010 namespace Thread { 00011 template<typename M> 00012 /** A mailbox that supports thread-safe addition and 00013 * retrieval of messages. 00014 */ 00015 class MailBox: public Dv::Thread::Monitor { 00016 public: 00017 /** Constructor. 00018 * @param name of mailbox, used for tracing. 00019 * @param max_capacity an attempt to put more 00020 * than max_capacity messages will cause MailBox::put 00021 * to throw an exception. If 0, capacity is unlimited. 00022 */ 00023 MailBox(const std::string& name, size_t max_capacity = 0, 00024 unsigned int min_debug_level = 0, Debugable* debug_master=0): 00025 Monitor(name, 2, min_debug_level, debug_master), max_capacity_(max_capacity), 00026 messages_() { 00027 } 00028 /** Put a message in the mailbox. 00029 * @param m message to store in the mailbox. 00030 * Note that a copy of the message will be made. 00031 * Use Dv::shared_ptr if you want to put a pointer. 00032 * @exception std::runtime_error if max_capacity is reached 00033 * @sa Dv::shared_ptr 00034 */ 00035 void put(const M& m) { 00036 Lock lock(*this); 00037 if (max_capacity_) 00038 if (messages_.size() >= max_capacity_) 00039 throw std::runtime_error("capacity (" 00040 + Dv::tostring(max_capacity_) + ") of mailbox " + name() 00041 + " exceeded"); 00042 log(2) << FUNCTION_S << " (" << Thread::self_id() << ")" << std::endl; 00043 messages_.push_back(m); 00044 signal(MAILBOX_NONEMPTY); 00045 } 00046 00047 /** @return max capacity of this mailbox */ 00048 const size_t max_capacity() const { return max_capacity_; } 00049 00050 /** Get a message from a mailbox. This function will 00051 * block until a message is available. 00052 * @param millisec_to_wait time to wait for message if none 00053 * are available; if the time has passed and no messages 00054 * are available, a std::runtime_error is thrown. 00055 * @exception std::runtime_error if no messages are available 00056 * after waiting @c millisec_to_wait millisecs 00057 */ 00058 M get(size_t millisec_to_wait = 2000) { 00059 Lock lock(*this); 00060 while (messages_.size() == 0) { 00061 if (!wait(MAILBOX_NONEMPTY, millisec_to_wait)) 00062 throw std::runtime_error(name() + 00063 ": MailBox::get() timed out after " + Dv::tostring(millisec_to_wait) 00064 + " millisec"); 00065 } 00066 00067 M m = messages_.front(); 00068 messages_.pop_front(); 00069 log(2) << FUNCTION_S << std::endl; 00070 return m; 00071 } 00072 00073 /** @return number of pending messages. */ 00074 size_t size() const { return messages_.size(); } 00075 00076 private: 00077 enum { MAILBOX_NONEMPTY = 0 }; 00078 size_t max_capacity_; 00079 std::deque<M> messages_; 00080 }; 00081 } 00082 } 00083 #endif
dvthread-0.13.4 | [11 December, 2009] |