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  virtual
425  ~Request_waiter() = default;
426 
427  private:
428  friend class Locker;
429 
431  std::mutex mutex;
433  std::condition_variable cond_var;
434 
438  template <class Container_list>
439  int
440  Wait_and_process_impl(const Container_list &containers,
441  std::chrono::milliseconds timeout,
442  int requests_limit, Predicate ext_predicate);
443  };
444 
446  enum class Type {
448  NONE = 0x0,
450  PROCESSOR = 0x1,
452  COMPLETION_CONTEXT = 0x2,
454  ANY = PROCESSOR | COMPLETION_CONTEXT,
456  TEMPORAL = 0x4,
458  TEMP_COMPLETION_CONTEXT = COMPLETION_CONTEXT | TEMPORAL
459  };
460 
463  const std::string& name,
465 
466  virtual
468 
470  virtual Type
471  Get_type() const
472  {
473  return Type::NONE;
474  }
475 
477  bool
479  {
480  return static_cast<int>(Get_type()) & static_cast<int>(mask);
481  }
482 
488  void
489  Submit_request(Request::Ptr request);
490 
494  void
496  Request::Ptr request,
497  Request_waiter::Locker locker);
498 
504  int
505  Process_requests(int requests_limit = 0);
506 
515  int
516  Process_requests(std::unique_lock<std::mutex> &lock, int requests_limit = 0);
517 
522  void
524 
527  Get_waiter() const
528  {
529  return waiter;
530  }
531 
533  const std::string&
535  {
536  return name;
537  }
538 
543  void
544  Enable();
545 
553  void
554  Disable();
555 
557  bool
558  Is_enabled() const;
559 
560 protected:
568  std::list<Request::Ptr> request_queue;
569 
573  void
574  Processing_loop();
575 
579  virtual void
580  Process_request(Request::Ptr request) = 0;
581 
586  virtual void
587  On_enable();
588 
596  virtual void
597  On_disable();
598 
600  void
601  Set_disabled();
602 
607  virtual void
609 
610 private:
612  void
613  Submit_request_impl(
614  Request::Ptr request,
615  Request_waiter::Locker locker);
616 
618  void
619  Abort_requests();
620 
622  std::atomic_bool is_enabled = { false };
623 
625  std::atomic_bool disable_ongoing = { false };
626 
631  std::atomic_bool abort_ongoing = { false };
632 
634  const std::string name;
635 
637  std::list<Request::Ptr> aborted_request_queue;
638 };
639 
642 
647 public:
654  Locker(Request_waiter::Ptr waiter, bool want_notify = false);
655 
656  ~Locker();
657 
659  Locker(const Locker &) = delete;
660 
662  Locker(Locker &&);
663 
667  void
668  Lock();
669 
673  void
674  Unlock();
675 
677  bool
678  Want_notify() const;
679 
681  bool
682  Is_same_waiter(const Request_waiter::Ptr&) const;
683 
684 private:
688  bool want_notify;
690  bool is_locked;
691 };
692 
695 
696 } /* namespace vsm */
697 } /* namespace ugcs */
698 
699 #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:568
void Disable()
Disable the container.
virtual Type Get_type() const
Get this container type.
Definition: request_container.h:471
Request_waiter::Ptr waiter
Waiter associated with this container.
Definition: request_container.h:564
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:641
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:527
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:646
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:478
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:446
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:534
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:694
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