VSM C++ SDK
Vehicle Specific Modules SDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
request_container.h
Go to the documentation of this file.
1 // Copyright (c) 2018, Smart Projects Holdings Ltd
2 // All rights reserved.
3 // See LICENSE file for license details.
4 
11 #ifndef _UGCS_VSM_REQUEST_CONTAINER_H_
12 #define _UGCS_VSM_REQUEST_CONTAINER_H_
13 
14 #include <ugcs/vsm/callback.h>
15 #include <ugcs/vsm/utils.h>
16 
17 #include <memory>
18 #include <mutex>
19 #include <chrono>
20 #include <condition_variable>
21 #include <atomic>
22 #include <list>
23 
24 namespace ugcs {
25 namespace vsm {
26 
30 class Request_container: public std::enable_shared_from_this<Request_container> {
32 
33 public:
37  class Request: public std::enable_shared_from_this<Request> {
38  DEFINE_COMMON_CLASS(Request, Request)
39 
40  public:
44  enum class Status {
48  PENDING,
52  CANCELLATION_PENDING,
56  CANCELING,
60  PROCESSING,
69  ABORT_PENDING,
72  ABORTED,
73 
77  RESULT_CODES,
78 
80  OK = RESULT_CODES,
82  CANCELED
83  };
84 
88  typedef std::unique_lock<std::mutex> Locker;
89 
90  virtual
91  ~Request();
92 
99  void
100  Set_processing_handler(const Handler &handler);
101 
103  void
104  Set_processing_handler(Handler &&handler);
105 
113  void
114  Set_completion_handler(const Request_container::Ptr &context,
115  const Handler &handler);
116 
118  void
119  Set_completion_handler(const Request_container::Ptr &context,
120  Handler &&handler);
121 
137  void
138  Set_cancellation_handler(const Handler &handler);
139 
141  void
142  Set_cancellation_handler(Handler &&handler);
143 
151  void
152  Set_done_handler(Handler &handler);
153 
155  void
156  Set_done_handler(Handler &&handler);
157 
162  Get_completion_context(Locker locker = Locker()) const;
163 
173  void
174  Process(bool process_request);
175 
187  void
188  Complete(Status status = Status::OK, Locker locker = Locker());
189 
198  void
199  Cancel(Locker locker = Locker());
200 
211  void
212  Abort(Locker locker = Locker());
213 
223  Locker
224  Lock(bool acquire = true) const;
225 
227  Status
228  Get_status() const
229  {
230  return status;
231  }
232 
234  bool
235  Is_completed() const
236  {
237  return status >= Status::RESULT_CODES;
238  }
239 
243  bool
245  {
246  /* Abort pending is only for completion contexts. */
247  return !Is_completed() && Get_status() != Status::ABORT_PENDING;
248  }
249 
251  bool
252  Is_aborted() const
253  {
254  return status == Status::ABORTED || status == Status::ABORT_PENDING;
255  }
256 
258  bool
260  {
261  return status == Status::PROCESSING;
262  }
263 
265  bool
267  {
268  return completion_delivered;
269  }
270 
274  bool
276  {
277  return completion_processed && !completion_handler;
278  }
279 
283  bool
284  Is_done() const
285  {
286  return Is_completion_delivered() || Is_aborted();
287  }
288 
300  bool
301  Wait_done(bool process_ctx = true,
302  std::chrono::milliseconds timeout = std::chrono::milliseconds::zero());
303 
305  bool&
307  {
308  return timed_out;
309  }
310 
311  protected:
315  virtual void
316  Destroy();
317 
324  bool
325  Is_completion_handler_present();
326 
327  private:
329  Handler processing_handler;
331  Handler completion_handler;
335  Handler cancellation_handler;
339  Handler done_handler;
341  Request_container::Ptr completion_context;
346  bool timed_out = false;
347  std::atomic<Status> status = { Status::PENDING };
349  std::atomic_bool completion_processed = { false },
351  completion_delivered = { false };
353  mutable std::mutex mutex;
355  std::condition_variable cond_var;
356  };
357 
361  class Request_waiter: public std::enable_shared_from_this<Request_waiter> {
363 
364  public:
368  typedef Callback_base<bool>::Ptr<> Predicate;
369 
370  class Locker;
371 
373  virtual void
374  Notify();
375 
377  Locker
378  Lock();
379 
385  Locker
386  Lock_notify();
387 
401  int
402  Wait_and_process(const std::initializer_list<Request_container::Ptr> &containers,
403  std::chrono::milliseconds timeout = std::chrono::milliseconds::zero(),
404  int requests_limit = 0, Predicate predicate = Predicate());
405 
419  int
420  Wait_and_process(const std::list<Request_container::Ptr> &containers,
421  std::chrono::milliseconds timeout = std::chrono::milliseconds::zero(),
422  int requests_limit = 0, Predicate predicate = Predicate());
423 
424  private:
425  friend class Locker;
426 
428  std::mutex mutex;
430  std::condition_variable cond_var;
431 
435  template <class Container_list>
436  int
437  Wait_and_process_impl(const Container_list &containers,
438  std::chrono::milliseconds timeout,
439  int requests_limit, Predicate ext_predicate);
440  };
441 
443  enum class Type {
445  NONE = 0x0,
447  PROCESSOR = 0x1,
449  COMPLETION_CONTEXT = 0x2,
451  ANY = PROCESSOR | COMPLETION_CONTEXT,
453  TEMPORAL = 0x4,
455  TEMP_COMPLETION_CONTEXT = COMPLETION_CONTEXT | TEMPORAL
456  };
457 
460  const std::string& name,
462 
463  virtual
465 
467  virtual Type
468  Get_type() const
469  {
470  return Type::NONE;
471  }
472 
474  bool
476  {
477  return static_cast<int>(Get_type()) & static_cast<int>(mask);
478  }
479 
485  void
486  Submit_request(Request::Ptr request);
487 
491  void
493  Request::Ptr request,
494  Request_waiter::Locker locker);
495 
501  int
502  Process_requests(int requests_limit = 0);
503 
512  int
513  Process_requests(std::unique_lock<std::mutex> &lock, int requests_limit = 0);
514 
519  void
521 
524  Get_waiter() const
525  {
526  return waiter;
527  }
528 
530  const std::string&
532  {
533  return name;
534  }
535 
540  void
541  Enable();
542 
550  void
551  Disable();
552 
554  bool
555  Is_enabled() const;
556 
557 protected:
565  std::list<Request::Ptr> request_queue;
566 
570  void
571  Processing_loop();
572 
576  virtual void
577  Process_request(Request::Ptr request) = 0;
578 
583  virtual void
584  On_enable();
585 
593  virtual void
594  On_disable();
595 
597  void
598  Set_disabled();
599 
604  virtual void
606 
607 private:
609  void
610  Submit_request_impl(
611  Request::Ptr request,
612  Request_waiter::Locker locker);
613 
615  void
616  Abort_requests();
617 
619  std::atomic_bool is_enabled = { false };
620 
622  std::atomic_bool disable_ongoing = { false };
623 
628  std::atomic_bool abort_ongoing = { false };
629 
631  const std::string name;
632 
634  std::list<Request::Ptr> aborted_request_queue;
635 };
636 
639 
644 public:
651  Locker(Request_waiter::Ptr waiter, bool want_notify = false);
652 
653  ~Locker();
654 
656  Locker(const Locker &) = delete;
657 
659  Locker(Locker &&);
660 
664  void
665  Lock();
666 
670  void
671  Unlock();
672 
674  bool
675  Want_notify() const;
676 
678  bool
679  Is_same_waiter(const Request_waiter::Ptr&) const;
680 
681 private:
685  bool want_notify;
687  bool is_locked;
688 };
689 
692 
693 } /* namespace vsm */
694 } /* namespace ugcs */
695 
696 #endif /* _UGCS_VSM_REQUEST_CONTAINER_H_ */
void Submit_request_locked(Request::Ptr request, Request_waiter::Locker locker)
The same as Submit_request, but with previously acquired lock of the associated waiter.
virtual void Notify()
Notify all listeners about request submission.
bool Is_completion_delivering_started() const
Check if the request completion handler already invoked (but might not be returned yet...
Definition: request_container.h:275
Generic request for implementing inter-threads communications and asynchronous operations.
Definition: request_container.h:37
void Set_disabled()
Disable the container and notify its waiter.
None type used in base class.
std::list< Request::Ptr > request_queue
Queue of pending requests, i.e.
Definition: request_container.h:565
void Disable()
Disable the container.
virtual Type Get_type() const
Get this container type.
Definition: request_container.h:468
Request_waiter::Ptr waiter
Waiter associated with this container.
Definition: request_container.h:561
bool & Timed_out()
Access timed_out member.
Definition: request_container.h:306
virtual void Process_request(Request::Ptr request)=0
Process request.
virtual void On_enable()
Called when the container is enabled.
virtual void On_wait_and_process()
Called when default processing loop want to wait for work and process it.
Request_container::Request_waiter Request_waiter
Request waiter type for convenient usage.
Definition: request_container.h:638
Callback_base< void >::Ptr<> Handler
Callback denoting a handler of the request.
Definition: request_container.h:86
Callback which can be executed.
Definition: callback.h:86
Locker Lock_notify()
Acquire lock for request submission.
Generic callback which can be used to define and create an instance of an abstract callable operation...
bool Is_request_processing_needed() const
Return true only if the request processing (i.e.
Definition: request_container.h:244
Request_waiter::Ptr Get_waiter() const
Get request waiter associated with this container.
Definition: request_container.h:524
Various common utilities.
std::shared_ptr< Request > Ptr
Pointer type.
Definition: request_container.h:38
Helper class for RAII-based locking and notifying Request_waiter objects.
Definition: request_container.h:643
Operation completed successfully.
static Ptr Create(Args &&...args)
Create an instance.
Definition: request_container.h:362
void Processing_loop()
Request processing loop implementation.
std::shared_ptr< Request_waiter > Ptr
Pointer type.
Definition: request_container.h:362
Request_container(const std::string &name, Request_waiter::Ptr waiter=Request_waiter::Create())
Create container with default associated waiter.
bool Is_aborted() const
Check if request is aborted.
Definition: request_container.h:252
Pointer class type.
Definition: callback.h:93
int Process_requests(int requests_limit=0)
Process all currently queued requests.
Status
Request processing status which is returned by the handler or set internally.
Definition: request_container.h:44
bool Check_type(Type mask)
Check if the container type conforms the specified characteristic mask.
Definition: request_container.h:475
Status Get_status() const
Get request current status.
Definition: request_container.h:228
bool Is_completion_delivered() const
Check if the request completion notification is delivered.
Definition: request_container.h:266
std::shared_ptr< Request_container > Ptr
Pointer type.
Definition: request_container.h:31
bool Is_done() const
Check if request is fully processed, i.e.
Definition: request_container.h:284
Operation canceled.
Generic container for queued requests.
Definition: request_container.h:30
Type
Container type.
Definition: request_container.h:443
virtual void On_disable()
Called when the container is terminated.
int Wait_and_process(const std::initializer_list< Request_container::Ptr > &containers, std::chrono::milliseconds timeout=std::chrono::milliseconds::zero(), int requests_limit=0, Predicate predicate=Predicate())
Wait for request submission.
void Set_waiter(Request_waiter::Ptr waiter)
Set request waiter associated with this container.
std::unique_lock< std::mutex > Locker
Smart lock object for request external locking.
Definition: request_container.h:88
bool Is_completed() const
Check if request is completed.
Definition: request_container.h:235
const std::string & Get_name()
Get the name of the container.
Definition: request_container.h:531
void Submit_request(Request::Ptr request)
Submit request to this container for further processing or notification handlers invocation.
bool Is_enabled() const
Check if the container is currently enabled.
bool Is_processing() const
Check if request is still processing.
Definition: request_container.h:259
#define DEFINE_COMMON_CLASS(__class_name,...)
Use this macro to define some common attributes for a class.
Definition: utils.h:25
Request_container::Request Request
Request type for convenient usage.
Definition: request_container.h:691
Locker Lock()
Acquire lock for request getting.
void Enable()
Enable the container.
Represents request synchronization entity which is used for request queues protected access...
Definition: request_container.h:361