No-op: remove all trailing whitespace.
[dcpomatic.git] / src / lib / signaller.h
1 /*
2     Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef DCPOMATIC_SIGNALLER_H
21 #define DCPOMATIC_SIGNALLER_H
22
23 #include "signal_manager.h"
24 #include <boost/thread/mutex.hpp>
25 #include <boost/signals2.hpp>
26
27 class WrapperBase
28 {
29 public:
30         WrapperBase ()
31                 : _valid (true)
32                 , _finished (false)
33         {}
34
35         virtual ~WrapperBase () {}
36
37         /* Can be called from any thread */
38         void invalidate ()
39         {
40                 boost::mutex::scoped_lock lm (_mutex);
41                 _valid = false;
42         }
43
44         bool finished () const {
45                 boost::mutex::scoped_lock lm (_mutex);
46                 return _finished;
47         }
48
49 protected:
50         /* Protect _valid and _finished */
51         mutable boost::mutex _mutex;
52         bool _valid;
53         bool _finished;
54 };
55
56 /** Helper class to manage lifetime of signals, specifically to address
57  *  the problem where an object containing a signal is deleted before
58  *  its signal is emitted.
59  */
60 template <class T>
61 class Wrapper : public WrapperBase
62 {
63 public:
64         Wrapper (T signal)
65                 : _signal (signal)
66         {
67
68         }
69
70         /* Called by the UI thread only */
71         void signal ()
72         {
73                 boost::mutex::scoped_lock lm (_mutex);
74                 if (_valid) {
75                         _signal ();
76                 }
77                 _finished = true;
78         }
79
80 private:
81         T _signal;
82 };
83
84 /** Parent for any class which needs to raise cross-thread signals (from non-UI
85  *  to UI).  Subclasses should call, e.g. emit (boost::bind (boost::ref (MySignal), foo, bar));
86  */
87 class Signaller
88 {
89 public:
90         /* Can be called from any thread */
91         virtual ~Signaller () {
92                 boost::mutex::scoped_lock lm (_signaller_mutex);
93                 for (std::list<WrapperBase*>::iterator i = _wrappers.begin(); i != _wrappers.end(); ++i) {
94                         (*i)->invalidate ();
95                 }
96         }
97
98         /* Can be called from any thread */
99         template <class T>
100         void emit (T signal)
101         {
102                 Wrapper<T>* w = new Wrapper<T> (signal);
103                 if (signal_manager) {
104                         signal_manager->emit (boost::bind (&Wrapper<T>::signal, w));
105                 }
106
107                 boost::mutex::scoped_lock lm (_signaller_mutex);
108
109                 /* Clean up finished Wrappers */
110                 std::list<WrapperBase*>::iterator i = _wrappers.begin ();
111                 while (i != _wrappers.end ()) {
112                         std::list<WrapperBase*>::iterator tmp = i;
113                         ++tmp;
114                         if ((*i)->finished ()) {
115                                 delete *i;
116                                 _wrappers.erase (i);
117                         }
118                         i = tmp;
119                 }
120
121                 /* Add the new one */
122                 _wrappers.push_back (w);
123         }
124
125 private:
126         /* Protect _wrappers */
127         boost::mutex _signaller_mutex;
128         std::list<WrapperBase*> _wrappers;
129 };
130
131 #endif