Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers scheduler.hpp Source File

scheduler.hpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_NODE_SCHEDULER_HPP_INCLUDED
00006 #define UAVCAN_NODE_SCHEDULER_HPP_INCLUDED
00007 
00008 #include <uavcan/error.hpp>
00009 #include <uavcan/util/linked_list.hpp>
00010 #include <uavcan/transport/dispatcher.hpp>
00011 
00012 namespace uavcan
00013 {
00014 
00015 class UAVCAN_EXPORT Scheduler;
00016 
00017 class UAVCAN_EXPORT DeadlineHandler : public LinkedListNode<DeadlineHandler>
00018 {
00019     MonotonicTime deadline_;
00020 
00021 protected:
00022     Scheduler& scheduler_;
00023 
00024     explicit DeadlineHandler(Scheduler& scheduler)
00025         : scheduler_(scheduler)
00026     { }
00027 
00028     virtual ~DeadlineHandler() { stop(); }
00029 
00030 public:
00031     virtual void handleDeadline(MonotonicTime current) = 0;
00032 
00033     void startWithDeadline(MonotonicTime deadline);
00034     void startWithDelay(MonotonicDuration delay);
00035     void generateDeadlineImmediately() { startWithDeadline(MonotonicTime::fromUSec(1)); }
00036 
00037     void stop();
00038 
00039     bool isRunning() const;
00040 
00041     MonotonicTime getDeadline() const { return deadline_; }
00042     Scheduler& getScheduler() const { return scheduler_; }
00043 };
00044 
00045 
00046 class UAVCAN_EXPORT DeadlineScheduler : Noncopyable
00047 {
00048     LinkedListRoot<DeadlineHandler> handlers_;  // Ordered by deadline, lowest first
00049 
00050 public:
00051     void add(DeadlineHandler* mdh);
00052     void remove(DeadlineHandler* mdh);
00053     bool doesExist(const DeadlineHandler* mdh) const;
00054     unsigned getNumHandlers() const { return handlers_.getLength(); }
00055 
00056     MonotonicTime pollAndGetMonotonicTime(ISystemClock& sysclock);
00057     MonotonicTime getEarliestDeadline() const;
00058 };
00059 
00060 /**
00061  * This class distributes processing time between library components (IO handling, deadline callbacks, ...).
00062  */
00063 class UAVCAN_EXPORT Scheduler : Noncopyable
00064 {
00065     enum { DefaultDeadlineResolutionMs = 5 };
00066     enum { MinDeadlineResolutionMs = 1 };
00067     enum { MaxDeadlineResolutionMs = 100 };
00068 
00069     enum { DefaultCleanupPeriodMs = 1000 };
00070     enum { MinCleanupPeriodMs = 10 };
00071     enum { MaxCleanupPeriodMs = 10000 };
00072 
00073     DeadlineScheduler deadline_scheduler_;
00074     Dispatcher dispatcher_;
00075     MonotonicTime prev_cleanup_ts_;
00076     MonotonicDuration deadline_resolution_;
00077     MonotonicDuration cleanup_period_;
00078     bool inside_spin_;
00079 
00080     struct InsideSpinSetter
00081     {
00082         Scheduler& owner;
00083         InsideSpinSetter(Scheduler& o)
00084             : owner(o)
00085         {
00086             owner.inside_spin_ = true;
00087         }
00088         ~InsideSpinSetter() { owner.inside_spin_ = false; }
00089     };
00090 
00091     MonotonicTime computeDispatcherSpinDeadline(MonotonicTime spin_deadline) const;
00092     void pollCleanup(MonotonicTime mono_ts, uint32_t num_frames_processed_with_last_spin);
00093 
00094 public:
00095     Scheduler(ICanDriver& can_driver, IPoolAllocator& allocator, ISystemClock& sysclock)
00096         : dispatcher_(can_driver, allocator, sysclock)
00097         , prev_cleanup_ts_(sysclock.getMonotonic())
00098         , deadline_resolution_(MonotonicDuration::fromMSec(DefaultDeadlineResolutionMs))
00099         , cleanup_period_(MonotonicDuration::fromMSec(DefaultCleanupPeriodMs))
00100         , inside_spin_(false)
00101     { }
00102 
00103     /**
00104      * Spin until the deadline, or until some error occurs.
00105      * This function will return strictly when the deadline is reached, even if there are unprocessed frames.
00106      * Returns negative error code.
00107      */
00108     int spin(MonotonicTime deadline);
00109 
00110     /**
00111      * Non-blocking version of @ref spin() - spins until all pending frames and events are processed,
00112      * or until some error occurs. If there's nothing to do, returns immediately.
00113      * Returns negative error code.
00114      */
00115     int spinOnce();
00116 
00117     DeadlineScheduler& getDeadlineScheduler() { return deadline_scheduler_; }
00118 
00119     Dispatcher& getDispatcher()             { return dispatcher_; }
00120     const Dispatcher& getDispatcher() const { return dispatcher_; }
00121 
00122     ISystemClock& getSystemClock()         { return dispatcher_.getSystemClock(); }
00123     MonotonicTime getMonotonicTime() const { return dispatcher_.getSystemClock().getMonotonic(); }
00124     UtcTime getUtcTime()             const { return dispatcher_.getSystemClock().getUtc(); }
00125 
00126     /**
00127      * Worst case deadline callback resolution.
00128      * Higher resolution increases CPU usage.
00129      */
00130     MonotonicDuration getDeadlineResolution() const { return deadline_resolution_; }
00131     void setDeadlineResolution(MonotonicDuration res)
00132     {
00133         res = min(res, MonotonicDuration::fromMSec(MaxDeadlineResolutionMs));
00134         res = max(res, MonotonicDuration::fromMSec(MinDeadlineResolutionMs));
00135         deadline_resolution_ = res;
00136     }
00137 
00138     /**
00139      * How often the scheduler will run cleanup (listeners, outgoing transfer registry, ...).
00140      * Cleanup execution time grows linearly with number of listeners and number of items
00141      * in the Outgoing Transfer ID registry.
00142      * Lower period increases CPU usage.
00143      */
00144     MonotonicDuration getCleanupPeriod() const { return cleanup_period_; }
00145     void setCleanupPeriod(MonotonicDuration period)
00146     {
00147         period = min(period, MonotonicDuration::fromMSec(MaxCleanupPeriodMs));
00148         period = max(period, MonotonicDuration::fromMSec(MinCleanupPeriodMs));
00149         cleanup_period_ = period;
00150     }
00151 };
00152 
00153 }
00154 
00155 #endif // UAVCAN_NODE_SCHEDULER_HPP_INCLUDED