first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / processes / mailbox.h
1 #ifndef MAILBOX_CLASS
2 #define MAILBOX_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : mailbox                                                           *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
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 \*****************************************************************************/
17
18 #include <basis/mutex.h>
19 #include <structures/set.h>
20 #include <structures/unique_id.h>
21
22 namespace processes {
23
24 class letter;
25 class mailbox_bank;
26
27 //! Implements a thread safe "mail" delivery system.
28 /*!
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.
34 */
35
36 class mailbox : public virtual basis::root_object
37 {
38 public:
39   mailbox();
40   virtual ~mailbox();
41
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. */
48
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
58     for memory leaks. */
59
60   int waiting(const structures::unique_int &id) const;
61     //!< returns the number of items waiting for the "id" specified, if any.
62
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. */
67
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
73     to clear up. */
74
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. */
78
79   void clean_up();
80     //!< removes any empty mailboxes from our list.
81
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. */
89
90   enum apply_outcomes {
91     OKAY = basis::common::OKAY,   //!< continue apply process.
92
93     DEFINE_OUTCOME(APPLY_STOP, -46, "Halt the apply process"),
94     DEFINE_OUTCOME(APPLY_WHACK, -47, "Removes the current letter, but "
95         "continues"),
96     DEFINE_OUTCOME(APPLY_WHACK_STOP, -48, "Halts apply and trashes the "
97         "current letter")
98   };
99
100   typedef basis::outcome apply_function(letter &current, 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. */
110
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
117     from "to_apply". */
118
119 private:
120   basis::mutex *_transaction_lock;  //!< keeps the state of the mailbox safe.
121   mailbox_bank *_packages;  //!< the collection of mail that has arrived.
122
123   // prohibited.
124   mailbox(const mailbox &);
125   mailbox &operator =(const mailbox &);
126 };
127
128 } //namespace.
129
130 #endif
131