00001 /** 00002 * @file mailbox.h 00003 * @author Reshen Amin <reshen@zensrc.com> 00004 * 00005 * @brief Contains the struct definition for @ref Mailbox 00006 * 00007 * @license Byzantine Generals Problem Coding Sample.<br> 00008 * Copyright (C) 2010 Reshen Amin.<br> 00009 * See @ref license_sec for details.<br> 00010 */ 00011 00012 #ifndef SRC_MAILBOX_H_ 00013 #define SRC_MAILBOX_H_ 00014 00015 #include <boost/interprocess/sync/interprocess_semaphore.hpp> 00016 #include <boost/interprocess/allocators/allocator.hpp> 00017 00018 #include "orderqueue.h" 00019 00020 /** 00021 * @brief Plain Old Data (POD) container for a General's end point of 00022 * communication. Each general owns exactly one Mailbox, where other 00023 * Generals can place Orders bound for the owning general. The owning 00024 * general only reads from the contained @ref OrderQueue, while other 00025 * generals only write to the contained @ref OrderQueue. In this way, 00026 * the @ref OrderQueue models a multi-producer, single-consumer problem. 00027 */ 00028 struct Mailbox { 00029 /** 00030 * @brief The owning Lieutenant General waits on this semaphore to 00031 * be non-zero (always in the range of [0, 1]), which indicates that 00032 * a single round's work can commence. It is easiest to think of this in 00033 * terms of "this semaphore tracks the number of rounds the owning general 00034 * may perform." 00035 */ 00036 boost::interprocess::interprocess_semaphore sem_round_empty; 00037 00038 /** 00039 * @brief The single Commanding General waits on this semaphore to be 00040 * non-zero (always in the range of [0, 1]), which indicates that the 00041 * owning Lieutenant General has completed the current round. It is easiest 00042 * to think of this in terms of "this semaphore tracks the number of rounds 00043 * the owning general just completed." 00044 */ 00045 boost::interprocess::interprocess_semaphore sem_round_fill; 00046 00047 /** 00048 * @brief The queue that stores transfer of ownership over Orders between 00049 * the writer (non-owning general) and reader (owning general). The Queue 00050 * operates as standard Queues do, in that its FIFO, where the first 00051 * contained @ref Order is the oldest and the last @ref Order is the newest. 00052 * Enqueue occurs at the back, dequeue from the front. 00053 */ 00054 OrderQueue orders; 00055 00056 /** 00057 * @brief Constructor. Our initialization list instantiates @ref 00058 * sem_round_empty to 0 and @ref sem_round_fill to 0 to indicate that the 00059 * owning Lieutenant General needs to wait on the Communication General 00060 * to begin. 00061 * 00062 * @param order_alloc The shared memory allocator that our @ref orders 00063 * should use when allocating an @ref Order. 00064 */ 00065 explicit Mailbox(const OrderAllocator &order_alloc): 00066 sem_round_empty(0), 00067 sem_round_fill(0), 00068 orders(order_alloc) { 00069 } 00070 00071 /** 00072 * @brief Destructor 00073 */ 00074 ~Mailbox() { 00075 /* Safety check that we've processed all of the orders in this 00076 * mailbox */ 00077 assert(orders.Empty() == true); 00078 } 00079 }; 00080 00081 #endif // SRC_MAILBOX_H_
1.6.3