LCOV - code coverage report
Current view: top level - xenolith/scene/director - XLScheduler.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 12 12 100.0 %
Date: 2024-05-12 00:16:13 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2021 Roman Katuntsev <sbkarr@stappler.org>
       3             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       6             :  of this software and associated documentation files (the "Software"), to deal
       7             :  in the Software without restriction, including without limitation the rights
       8             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             :  copies of the Software, and to permit persons to whom the Software is
      10             :  furnished to do so, subject to the following conditions:
      11             : 
      12             :  The above copyright notice and this permission notice shall be included in
      13             :  all copies or substantial portions of the Software.
      14             : 
      15             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             :  THE SOFTWARE.
      22             :  **/
      23             : 
      24             : #ifndef XENOLITH_SCENE_DIRECTOR_XLSCHEDULER_H_
      25             : #define XENOLITH_SCENE_DIRECTOR_XLSCHEDULER_H_
      26             : 
      27             : #include "XLNodeInfo.h"
      28             : #include "SPPriorityList.h"
      29             : #include "SPSubscription.h"
      30             : 
      31             : namespace STAPPLER_VERSIONIZED stappler::xenolith {
      32             : 
      33             : using SchedulerFunc = Function<void(const UpdateTime &)>;
      34             : 
      35             : struct SchedulerCallback {
      36             :         SchedulerFunc callback = nullptr;
      37             :     bool paused = false;
      38             :     bool removed = false;
      39             : 
      40        1149 :     SchedulerCallback() = default;
      41             : 
      42        2535 :     SchedulerCallback(SchedulerFunc &&fn, bool p)
      43        2535 :     : callback(move(fn)), paused(p) { }
      44             : };
      45             : 
      46             : class Scheduler : public Ref {
      47             : public:
      48             :         Scheduler();
      49             :         virtual ~Scheduler();
      50             : 
      51             :         bool init();
      52             : 
      53             :         void unschedule(const void *);
      54             :         void unscheduleAll();
      55             : 
      56             :         template <typename T>
      57             :         void scheduleUpdate(T *, int32_t p = 0, bool paused = false);
      58             : 
      59             :         void schedulePerFrame(SchedulerFunc &&callback, void *target, int32_t priority, bool paused);
      60             : 
      61             :         void update(const UpdateTime &);
      62             : 
      63             :         bool isPaused(void *) const;
      64             :         void resume(void *);
      65             :         void pause(void *);
      66             : 
      67             :         bool empty() const;
      68             : 
      69             : protected:
      70             :         struct ScheduledTemporary {
      71             :                 SchedulerFunc callback;
      72             :                 void *target;
      73             :                 int32_t priority;
      74             :                 bool paused;
      75             :         };
      76             : 
      77             :         bool _locked = false;
      78             :         const void *_currentTarget = nullptr;
      79             :         SchedulerCallback *_currentNode = nullptr;
      80             :         PriorityList<SchedulerCallback> _list;
      81             :         Vector<ScheduledTemporary> _tmp;
      82             : };
      83             : 
      84             : template <class T = Subscription>
      85             : class SchedulerListener {
      86             : public:
      87             :         using Callback = Function<void(Subscription::Flags)>;
      88             : 
      89             :         SchedulerListener(Scheduler *s = nullptr, const Callback &cb = nullptr, T *sub = nullptr);
      90             :         ~SchedulerListener();
      91             : 
      92             :         SchedulerListener(const SchedulerListener<T> &);
      93             :         SchedulerListener &operator= (const SchedulerListener<T> &);
      94             : 
      95             :         SchedulerListener(SchedulerListener<T> &&);
      96             :         SchedulerListener &operator= (SchedulerListener<T> &&);
      97             : 
      98             :         SchedulerListener &operator= (T *);
      99             : 
     100             :         inline operator T * () { return get(); }
     101             :         inline operator T * () const { return get(); }
     102             :         inline operator bool () const { return _binding; }
     103             : 
     104             :         inline T * operator->() { return get(); }
     105             :         inline const T * operator->() const { return get(); }
     106             : 
     107             :         void set(T *sub);
     108             :         T *get() const;
     109             : 
     110             :         void setScheduler(Scheduler *);
     111             :         Scheduler *getScheduler() const;
     112             : 
     113             :         void setCallback(const Callback &cb);
     114             :         const Callback &getCallback() const;
     115             : 
     116             :         void setDirty();
     117             :         void update(const UpdateTime &time);
     118             : 
     119             :         void check();
     120             : 
     121             : protected:
     122             :         void updateScheduler();
     123             :         void schedule();
     124             :         void unschedule();
     125             : 
     126             :         Scheduler *_scheduler = nullptr;
     127             :         Binding<T> _binding;
     128             :         Callback _callback;
     129             :         bool _dirty = false;
     130             :         bool _scheduled = false;
     131             : };
     132             : 
     133             : template <typename T, typename Enable = void>
     134             : class SchedulerUpdate {
     135             : public:
     136             :         static void scheduleUpdate(Scheduler *scheduler, T *target, int32_t p, bool paused) {
     137             :                 scheduler->schedulePerFrame([target] (const UpdateTime &time) {
     138             :                         target->update(time);
     139             :                 }, target, p, paused);
     140             :         }
     141             : };
     142             : 
     143             : template<class T>
     144             : class SchedulerUpdate<T, typename std::enable_if<std::is_base_of<Ref, T>::value>::type> {
     145             : public:
     146        2409 :         static void scheduleUpdate(Scheduler *scheduler, T *t, int32_t p, bool paused) {
     147        2409 :                 auto ref = static_cast<Ref *>(t);
     148        2409 :                 auto target = Rc<Ref>(ref);
     149             : 
     150      542011 :                 scheduler->schedulePerFrame([target = move(target)] (const UpdateTime &time) {
     151      269801 :                         ((T *)target.get())->update(time);
     152             :                 }, t, p, paused);
     153        2409 :         }
     154             : };
     155             : 
     156             : template <typename T>
     157        2409 : void Scheduler::scheduleUpdate(T *target, int32_t p, bool paused) {
     158        2409 :         SchedulerUpdate<T>::scheduleUpdate(this, target, p, paused);
     159        2409 : }
     160             : 
     161             : 
     162             : template <class T>
     163             : SchedulerListener<T>::SchedulerListener(Scheduler *s, const Callback &cb, T *sub)
     164             : : _scheduler(s), _binding(sub), _callback(cb) {
     165             :         static_assert(std::is_convertible<T *, Subscription *>::value, "Invalid Type for DataListener<T>!");
     166             :         updateScheduler();
     167             : }
     168             : 
     169             : template <class T>
     170             : SchedulerListener<T>::~SchedulerListener() {
     171             :         unschedule();
     172             : }
     173             : 
     174             : template <class T>
     175             : SchedulerListener<T>::SchedulerListener(const SchedulerListener<T> &other) : _binding(other._binding), _callback(other._callback) {
     176             :         updateScheduler();
     177             : }
     178             : 
     179             : template <class T>
     180             : SchedulerListener<T> &SchedulerListener<T>::operator= (const SchedulerListener<T> &other) {
     181             :         _binding = other._binding;
     182             :         _callback = other._callback;
     183             :         updateScheduler();
     184             :         return *this;
     185             : }
     186             : 
     187             : template <class T>
     188             : SchedulerListener<T>::SchedulerListener(SchedulerListener<T> &&other) : _binding(std::move(other._binding)), _callback(std::move(other._callback)) {
     189             :         other.updateScheduler();
     190             :         updateScheduler();
     191             : }
     192             : 
     193             : template <class T>
     194             : SchedulerListener<T> &SchedulerListener<T>::operator= (SchedulerListener<T> &&other) {
     195             :         _binding = std::move(other._binding);
     196             :         _callback = std::move(other._callback);
     197             :         other.updateScheduler();
     198             :         updateScheduler();
     199             :         return *this;
     200             : }
     201             : 
     202             : template <class T>
     203             : void SchedulerListener<T>::set(T *sub) {
     204             :         if (_binding != sub) {
     205             :                 _binding = Binding<T>(sub);
     206             :                 updateScheduler();
     207             :         }
     208             : }
     209             : 
     210             : template <class T>
     211             : SchedulerListener<T> &SchedulerListener<T>::operator= (T *sub) {
     212             :         set(sub);
     213             :         return *this;
     214             : }
     215             : 
     216             : template <class T>
     217             : T *SchedulerListener<T>::get() const {
     218             :         return _binding;
     219             : }
     220             : 
     221             : template <class T>
     222             : void SchedulerListener<T>::setScheduler(Scheduler *s) {
     223             :         unschedule();
     224             :         _scheduler = s;
     225             :         updateScheduler();
     226             : }
     227             : 
     228             : template <class T>
     229             : Scheduler *SchedulerListener<T>::getScheduler() const {
     230             :         return _scheduler;
     231             : }
     232             : 
     233             : template <class T>
     234             : void SchedulerListener<T>::setCallback(const Callback &cb) {
     235             :         _callback = cb;
     236             : }
     237             : 
     238             : template <class T>
     239             : const Function<void(Subscription::Flags)> &SchedulerListener<T>::getCallback() const {
     240             :         return _callback;
     241             : }
     242             : 
     243             : template <class T>
     244             : void SchedulerListener<T>::setDirty() {
     245             :         _dirty = true;
     246             : }
     247             : 
     248             : template <class T>
     249             : void SchedulerListener<T>::update(const UpdateTime &time) {
     250             :         if (_callback && _binding) {
     251             :                 auto val = _binding.check();
     252             :                 if (!val.empty() || _dirty) {
     253             :                         _dirty = false;
     254             :                         _callback(val);
     255             :                 }
     256             :         }
     257             : }
     258             : 
     259             : template <class T>
     260             : void SchedulerListener<T>::check() {
     261             :         update(UpdateTime());
     262             : }
     263             : 
     264             : template <class T>
     265             : void SchedulerListener<T>::updateScheduler() {
     266             :         if (_binding && !_scheduled) {
     267             :                 schedule();
     268             :         } else if (!_binding && _scheduled) {
     269             :                 unschedule();
     270             :         }
     271             : }
     272             : 
     273             : template <class T>
     274             : void SchedulerListener<T>::schedule() {
     275             :         if (_scheduler && _binding && !_scheduled) {
     276             :                 _scheduler->scheduleUpdate(this, 0, false);
     277             :                 _scheduled = true;
     278             :         }
     279             : }
     280             : 
     281             : template <class T>
     282             : void SchedulerListener<T>::unschedule() {
     283             :         if (_scheduled) {
     284             :                 _scheduler->unschedule(this);
     285             :                 _scheduled = false;
     286             :         }
     287             : }
     288             : 
     289             : }
     290             : 
     291             : #endif /* XENOLITH_SCENE_DIRECTOR_XLSCHEDULER_H_ */

Generated by: LCOV version 1.14