4 /*****************************************************************************\
7 * Author : Chris Koeritz *
9 *******************************************************************************
10 * Copyright (c) 1998-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
18 #include <basis/mutex.h>
19 #include <structures/set.h>
20 #include <structures/unique_id.h>
27 //! Implements a thread safe "mail" delivery system.
29 Senders can drop packages off into the mailbox and the receivers can get
30 those packages back out of it. The base class for all mail items is also
31 provided in this library (letter.h). The name of this object is slightly
32 misleading; this object is really more of a post office. Each unique id
33 has its own mailbox slot for receiving mail.
36 class mailbox : public virtual basis::root_object
42 void drop_off(const structures::unique_int &id, letter *package);
43 //!< drops a "package" in the mailbox for "id".
44 /*!< note that when you send a package to someone, you give up all
45 authority and control over that package. hopefully the end recipient
46 will eventually pick it up and then delete it. if the package is never
47 received, then this object will delete it. */
49 bool pick_up(const structures::unique_int &id, letter * &package);
50 //!< returns true if the mailbox for "id" had a "package" to be delivered.
51 /*!< don't forget to check multiple times on a true outcome, since there
52 could be more than one package waiting. false is returned when no more
53 mail is waiting. be careful; "package" could be a bomb. dynamic casts
54 seem appropriate as a method for ensuring that you get the type of
55 object you expect. note that once the invoker receives a package, it
56 is their responsibility to carefully manage it and then delete the
57 package after handling. not deleting the "package" pointer is grounds
60 int waiting(const structures::unique_int &id) const;
61 //!< returns the number of items waiting for the "id" specified, if any.
63 void get_ids(structures::int_set &to_fill);
64 //!< stuffs the set "to_fill" with the ids of all mailboxes present.
65 /*!< if you want only those mailboxes holding one or more letters, then
66 call the clean_up() method prior to this method. */
68 bool close_out(const structures::unique_int &id);
69 //!< dumps all packages stored for the "id" and shuts down its mailbox.
70 /*!< the destructors for those packages should never try to do anything
71 with the mailbox system or a deadlock could result. true is returned if
72 the "id" had a registered mailbox; false just indicates there was no box
75 void show(basis::astring &to_fill);
76 //!< provides a picture of what's waiting in the mailbox.
77 /*!< this relies on the derived letter's required text_form() function. */
80 //!< removes any empty mailboxes from our list.
82 void limit_boxes(int max_letters);
83 //!< establishes a limit on the number of letters.
84 /*!< this is a helper function for a very special mailbox; it has a
85 limited maximum size and any letters above the "max_letters" count will
86 be deleted. don't use this function on any mailbox where all letters
87 are important; your mailbox must have a notion of unreliability before
88 this would ever be appropriate. */
91 OKAY = basis::common::OKAY, //!< continue apply process.
93 DEFINE_OUTCOME(APPLY_STOP, -46, "Halt the apply process"),
94 DEFINE_OUTCOME(APPLY_WHACK, -47, "Removes the current letter, but "
96 DEFINE_OUTCOME(APPLY_WHACK_STOP, -48, "Halts apply and trashes the "
100 typedef basis::outcome apply_function(letter ¤t, int uid, void *data_link);
101 //!< the "apply_function" is what a user of apply() must provide.
102 /*!< the function will be called on every letter in the mailbox unless one
103 of the invocations returns APPLY_STOP or APPLY_WHACK_STOP; this causes
104 the apply process to stop (and zap the node for APPLY_WHACK). the "uid"
105 is the target for the "current" letter. the "data_link" provides a way
106 for the function to refer back to a parent class or data package of some
107 sort. note that all sorts of deadlocks will occur if your apply
108 function tries to do anything on the mailbox, even transitively. keep
109 those functions as simple as possible. */
111 void apply(apply_function *to_apply, void *data_link);
112 //!< calls the "to_apply" function on possibly every letter in the mailbox.
113 /*!< this iterates until the function returns a 'STOP' outcome. the
114 "data_link" pointer is passed to the apply function. NOTE: it is NOT safe
115 to rearrange or manipulate the mailbox in any way from your "to_apply"
116 function; the only changes allowed are those caused by the return value
120 basis::mutex *_transaction_lock; //!< keeps the state of the mailbox safe.
121 mailbox_bank *_packages; //!< the collection of mail that has arrived.
124 mailbox(const mailbox &);
125 mailbox &operator =(const mailbox &);