PVData C++  8.0.2
thread.h
1 /* thread.h */
2 /*
3  * Copyright information and license terms for this software can be
4  * found in the file LICENSE that is included with the distribution
5  */
6 /**
7  * @author mrk
8  */
9 #ifndef THREAD_H
10 #define THREAD_H
11 
12 #include <memory>
13 #include <sstream>
14 #include <stdexcept>
15 
16 #if __cplusplus>=201103L
17 #include <functional>
18 #endif
19 
20 #include <epicsThread.h>
21 #include <shareLib.h>
22 
23 #include <pv/noDefaultMethods.h>
24 #include <pv/pvType.h>
25 
26 
27 namespace epics { namespace pvData {
28 
29 enum ThreadPriority {
30  lowestPriority =epicsThreadPriorityLow,
31  lowerPriority =epicsThreadPriorityLow + 15,
32  lowPriority =epicsThreadPriorityMedium - 15,
33  middlePriority =epicsThreadPriorityMedium,
34  highPriority =epicsThreadPriorityMedium + 15,
35  higherPriority =epicsThreadPriorityHigh - 15,
36  highestPriority =epicsThreadPriorityHigh
37 };
38 
39 class Thread;
40 typedef std::tr1::shared_ptr<Thread> ThreadPtr;
41 typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
42 
43 typedef epicsThreadRunable Runnable;
44 
45 namespace detail {
46 template<typename C>
47 struct MethRunner : public epicsThreadRunable
48 {
49  typedef void(C::*fn_t)();
50  fn_t fn;
51  C* inst;
52  MethRunner(C* i, fn_t f) :fn(f), inst(i) {}
53  virtual ~MethRunner() {}
54  virtual void run()
55  {
56  (inst->*fn)();
57  }
58 };
59 } // namespace detail
60 
61 /**
62  * @brief C++ wrapper for epicsThread from EPICS base.
63  *
64  */
65 class epicsShareClass Thread : public epicsThread {
66  EPICS_NOT_COPYABLE(Thread)
67 public:
68  /** @brief Holds all the configuration necessary to launch a @class Thread
69  *
70  * The defaults may be used except for the runnable, which must be given
71  * either in the constructor, or the @method run() method.
72  *
73  * @note Instances of @class Config may not be reused.
74  *
75  * Defaults:
76  * name: ""
77  * priority: epicsThreadPriorityLow (aka epics::pvData::lowestPriority)
78  * stack size: epicsThreadStackSmall
79  * auto start: true
80  * runner: nil (must be set explictly)
81  *
82  @code
83  stuct bar { void meth(); ... } X;
84  // with a static thread name
85  Thread foo(Thread::Config(&X, &bar::meth)
86  .name("example")
87  .prio(epicsThreadPriorityHigh));
88 
89  // with a constructed thread name
90  Thread foo(Thread::Config(&X, &bar::meth)
91  .prio(epicsThreadPriorityHigh)
92  <<"example"<<1);
93  @endcode
94  */
95  class epicsShareClass Config
96  {
97  unsigned int p_prio, p_stack;
98  std::ostringstream p_strm;
99  bool p_autostart;
100  Runnable *p_runner;
101  typedef epics::auto_ptr<Runnable> p_owned_runner_t;
102  p_owned_runner_t p_owned_runner;
103  friend class Thread;
104  Runnable& x_getrunner();
105  void x_setdefault();
106 
107  public:
108  Config();
109  Config(Runnable *r);
110  Config(void(*fn)(void*), void *ptr);
111  template<typename C>
112  Config(C* inst, void(C::*meth)()) {this->x_setdefault();this->run(inst, meth);}
113 #if __cplusplus>=201103L
114  Config(std::function<void()>&& fn);
115 #endif
116 
117  Config& name(const std::string& n);
118  Config& prio(unsigned int p);
119  Config& stack(epicsThreadStackSizeClass s);
120  Config& autostart(bool a);
121 
122  //! Thread will execute Runnable::run()
123  Config& run(Runnable* r);
124  //! Thread will execute (*fn)(ptr)
125  Config& run(void(*fn)(void*), void *ptr);
126  //! Thread will execute (inst->*meth)()
127  template<typename C>
128  Config& run(C* inst, void(C::*meth)())
129  {
130  this->p_owned_runner.reset(new detail::MethRunner<C>(inst, meth));
131  this->p_runner = this->p_owned_runner.get();
132  return *this;
133  }
134 #if __cplusplus>=201103L
135  Config& run(std::function<void()>&& fn);
136 #endif
137 
138  //! Append to thread name string. Argument must be understood by std::ostream::operator<<
139  template<typename T>
140  Config& operator<<(T x) { this->p_strm<<x; return *this; }
141  };
142 
143  /**
144  *
145  * Constructor
146  * @param name thread name.
147  * @param priority priority is one of:
148  @code
149  enum ThreadPriority {
150  lowestPriority, lowerPriority, lowPriority,
151  middlePriority,
152  highPriority, higherPriority, highestPriority
153  };
154  @endcode
155  * @param runnable this is a c function
156  * @param stkcls stack size as specified by epicsThreadStackSizeClass
157  */
158  Thread(std::string name,
159  ThreadPriority priority,
160  Runnable *runnable,
161  epicsThreadStackSizeClass stkcls=epicsThreadStackBig);
162 
163  /**
164  *
165  * Constructor
166  * @param runnable this is a c function
167  * @name thread name.
168  * @param stkcls stack size as specified by epicsThreadStackSizeClass
169  * @param priority priority is one of:
170  @code
171  enum ThreadPriority {
172  lowestPriority, lowerPriority, lowPriority,
173  middlePriority,
174  highPriority, higherPriority, highestPriority
175  };
176  @endcode
177  */
178  Thread(Runnable &runnable,
179  std::string name,
180  unsigned int stksize,
181  unsigned int priority=lowestPriority);
182 
183  //! @brief Create a new thread using the given @class Config
184  //! @throws std::logic_error for improper @class Config (ie. missing runner)
185  Thread(Config& c);
186 
187  /**
188  * Destructor
189  */
190  ~Thread();
191 
192  static size_t num_instances;
193 private:
194  Config::p_owned_runner_t p_owned;
195 };
196 
197 
198 }}
199 #endif /* THREAD_H */
#define EPICS_NOT_COPYABLE(CLASS)
Disable implicit copyable.