1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2012-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_event_queue_h)
27 #define octave_event_queue_h 1
28 
29 #include "octave-config.h"
30 
31 #include <queue>
32 #include <memory>
33 
34 #include "action-container.h"
35 
36 namespace octave
37 {
38   class
39   event_queue : public action_container
40   {
41   public:
42 
event_queue(void)43     event_queue (void) : fifo () { }
44 
45     // No copying!
46 
47     event_queue (const event_queue&) = delete;
48 
49     event_queue& operator = (const event_queue&) = delete;
50 
51     // Destructor should not raise an exception, so all actions
52     // registered should be exception-safe.  If you're not sure, see
53     // event_queue_safe.
54 
~event_queue(void)55     ~event_queue (void) { run (); }
56 
run_first(void)57     void run_first (void)
58     {
59       if (! empty ())
60         {
61           // No leak on exception!
62           std::unique_ptr<elem> ptr (fifo.front ());
63           fifo.pop ();
64           ptr->run ();
65         }
66     }
67 
discard_first(void)68     void discard_first (void)
69     {
70       if (! empty ())
71         {
72           elem *ptr = fifo.front ();
73           fifo.pop ();
74           delete ptr;
75         }
76     }
77 
size(void)78     std::size_t size (void) const { return fifo.size (); }
79 
80   protected:
81 
add_action(elem * new_elem)82     void add_action (elem *new_elem)
83     {
84       fifo.push (new_elem);
85     }
86 
87     std::queue<elem *> fifo;
88   };
89 
90   // Like event_queue, but this one will guard against the
91   // possibility of seeing an exception (or interrupt) in the cleanup actions.
92   // Not that we can do much about it, but at least we won't crash.
93 
94   class
95   event_queue_safe : public event_queue
96   {
97   private:
98 
99     void warn_unhandled_exception (void) const;
100 
101   public:
102 
event_queue_safe(void)103     event_queue_safe (void) : event_queue () { }
104 
105     // No copying!
106 
107     event_queue_safe (const event_queue_safe&) = delete;
108 
109     event_queue_safe& operator = (const event_queue_safe&) = delete;
110 
~event_queue_safe(void)111     ~event_queue_safe (void)
112     {
113       while (! empty ())
114         {
115           try
116             {
117               run_first ();
118             }
119           catch (...) // Yes, the black hole.  Remember we're in a dtor.
120             {
121               warn_unhandled_exception ();
122             }
123         }
124     }
125   };
126 }
127 
128 #endif
129