MEL
Microthread & Execution library
Process.h
1 #pragma once
2 /*
3  * SPDX-FileCopyrightText: 2005,2022 Daniel Barrientos
4  * <danivillamanin@gmail.com>
5  *
6  * SPDX-License-Identifier: MIT
7  */
8 
9 #include <MelLibType.h>
10 
11 #include <mpl/binary.h>
12 using mel::mpl::binary;
13 
14 #include <core/Callback.h>
16 #include <memory>
17 #include <mpl/Tuple.h>
18 #include <stdint.h>
19 
20 #if defined( MEL_IOS ) || defined( MEL_MACOSX )
21 #include <TargetConditionals.h>
22 #endif
23 #if defined( MEL_X86_GCC ) || TARGET_CPU_X86 || defined( MEL_X86_MSVC )
24 #include <tasking/Process_X86.h>
25 #elif TARGET_CPU_X86_64
26 #include <tasking/Process_X64_MAC.h>
27 #elif TARGET_CPU_ARM64
28 #include <tasking/Process_ARM64_IPhone.h>
29 #elif defined( _ARM_GCC ) && ( !defined( MEL_IOS ) )
30 #include <tasking/Process_ARM_GCC.h>
31 #elif defined( MEL_IOS )
32 #if !TARGET_IPHONE_SIMULATOR
33 #if defined( __arm__ )
34 #include <tasking/Process_ARM_IPhone.h>
35 #elif defined( __arm64__ )
36 #include <tasking/Process_ARM64_IPhone.h>
37 #else
38 #pragma message "Unknown ARM architecture"
39 #endif
40 #else
41 #include <core/Process_X86.h>
42 #endif
43 #elif defined( MEL_ANDROID )
44 #include <tasking/Process_ARM_Android.h>
45 #elif defined( MEL_X64_GCC ) || defined( MEL_X64_CLANG )
46 #include <tasking/Process_X64_GCC.h>
47 #elif defined( MEL_WINDOWS ) && defined( MEL_X64_MSVC )
48 #include <tasking/Process_X64_MSVC.h>
49 #endif
50 #if defined( MEL_IOS ) || defined( MEL_MACOSX )
51 #define OPTIMIZE_FLAGS __attribute__( ( optnone ) )
52 #elif defined( MEL_ANDROID )
53 #define OPTIMIZE_FLAGS
54 #elif defined( _ARM_GCC ) || defined( MEL_X86_GCC ) || defined( MEL_X64_GCC )
55 #define OPTIMIZE_FLAGS __attribute__( ( optimize( 0 ) ) )
56 #elif defined( MEL_X64_CLANG )
57 #define OPTIMIZE_FLAGS __attribute__( ( optnone ) )
58 #elif defined( MEL_WINDOWS )
59 #define OPTIMIZE_FLAGS
60 #endif
61 namespace mel
62 {
70  namespace tasking
71  {
72  class ProcessScheduler; // predeclaration
102  class MEL_API Process :
104  public std::enable_shared_from_this<Process>,
105  public MThreadAttributtes
107  {
108 
110  static void _switchProcess() OPTIMIZE_FLAGS;
111 
112  public:
113  enum EProcessState : uint8_t
114  {
118  PREPARED_TO_DIE,
121  KILLING_WAITING_FOR_SCHEDULED,
123  DEAD
124  };
126  enum class ESwitchResult
127  {
128  ESWITCH_OK,
129  ESWITCH_WAKEUP,
131  ESWITCH_ERROR,
132  ESWITCH_KILL
133  };
134 
140  Process( unsigned short capacity = 0 );
141  virtual ~Process( void );
151  void pause();
152 
172  void kill( bool force = false );
176  virtual void reset();
181  inline void setPeriod( unsigned int value );
182 
183  EProcessState getState() const { return mState; }
187  inline bool getDead() const;
192  // inline bool getPreparedToDie() const;
194  inline unsigned int getPeriod() const;
198  unsigned int getElapsedTime() const;
205  inline uint64_t getLastUpdateTime() const;
206  inline void resetTime();
207 
211  inline ProcessScheduler* const getProcessScheduler() const;
212 
217  static ESwitchResult wait( unsigned int msegs ) OPTIMIZE_FLAGS;
228  static ESwitchResult
229  switchProcess( bool continueInmediately ) OPTIMIZE_FLAGS;
239  template <class F> static ESwitchResult sleepAndDo( F postSleep );
248  template <class F>
249  static ESwitchResult waitAndDo( unsigned int msegs,
250  F postWait ) OPTIMIZE_FLAGS;
257  static ESwitchResult sleep() OPTIMIZE_FLAGS;
258  inline bool getAsleep() const;
263  void wakeUp();
264 
265  private:
266  // static ESwitchResult _sleep( Callback<void,void>* )
267  // OPTIMIZE_FLAGS;
268  static mel::mpl::Tuple<TYPELIST( int, Process*, unsigned int )>
269  _preSleep() OPTIMIZE_FLAGS;
270  static ESwitchResult _postSleep(
271  mel::mpl::Tuple<TYPELIST( int, Process*, unsigned int )> )
272  OPTIMIZE_FLAGS;
273  // static ESwitchResult _wait( unsigned int msegs,
274  // Callback<void,void>* ) OPTIMIZE_FLAGS;
275  static mel::mpl::Tuple<TYPELIST( bool, Process* )>
276  _preWait() OPTIMIZE_FLAGS;
277  static ESwitchResult _postWait(
278  uint64_t msegs,
279  mel::mpl::Tuple<TYPELIST( bool, Process* )> ) OPTIMIZE_FLAGS;
280  EProcessState mState;
281  EProcessState mPreviousState;
282  volatile bool mWakeup; // temp value to know if context switch comes
283  // from a wakeup
284  bool mPauseReq;
285  unsigned int mPeriod;
286  uint64_t mLastUpdateTime;
288  mOwnerProcessScheduler;
293  void _execute( uint64_t msegs ) OPTIMIZE_FLAGS;
294  volatile void checkMicrothread( uint64_t msegs ) OPTIMIZE_FLAGS;
300  void update( uint64_t msegs ) OPTIMIZE_FLAGS;
304  inline void setDead();
305 
306  protected:
314  virtual void onUpdate( uint64_t msecs ) = 0;
320  virtual void onInit( uint64_t msecs ){};
327  virtual bool onKill() { return true; };
331  virtual void onPause(){};
336  virtual void onWakeUp() {}
340  virtual void killDone(){};
341 
342  friend class ProcessScheduler;
343  };
344 
345  void Process::setPeriod( unsigned int value ) { mPeriod = value; }
346 
347  void Process::setDead() { mState = EProcessState::DEAD; }
349  {
350  return mOwnerProcessScheduler;
351  }
352  /*bool Process::getDead() const
353  {
354  return (mState ==EProcessState:: DEAD );
355  }
356  bool Process::getPreparedToDie() const
357  {
358  return (mState == EProcessState::PREPARED_TO_DIE);
359  }*/
360  unsigned int Process::getPeriod() const { return mPeriod; }
361 
362  void Process::resetTime() { mLastUpdateTime = 0; }
363  // uint64_t Process::getPreviousTime() const
364  // {
365  // return mPreviousTime;
366  // }
367 
368  // uint64_t Process::getLastTime() const
369  // {
370  // return mLastTime;
371  // }
372  uint64_t Process::getLastUpdateTime() const { return mLastUpdateTime; }
373 
374  bool Process::getAsleep() const
375  {
376  return mState == EProcessState::ASLEEP && !mWakeup;
377  }
378 
379  template <class F>
381  F postWait )
382  {
383  auto v = _preWait();
384  // trigger callback
385  postWait();
386  return _postWait( msegs, v );
387  // return _wait( msegs,new Callback<void,void>(
388  // postWait,::core::use_functor ) );
389  }
390  template <class F>
392  {
393  auto v = _preSleep();
394  // trigger callback
395  postSleep();
396  return _postSleep( v );
397  // return _sleep( new Callback<void,void>(
398  // postSleep,::core::use_functor ) );
399  }
400  } // namespace tasking
401 } // namespace mel
create Callback from callable
Definition: Callback_Impl.h:142
A periodic task, implementing a microthread.
Definition: Process.h:107
virtual void onWakeUp()
Called when process is woken up.
Definition: Process.h:336
static ESwitchResult sleepAndDo(F postSleep)
Sleep current process and execute given callable. To reactivate to you must use wakeUp.
Definition: Process.h:391
static ESwitchResult switchProcess(bool continueInmediately) OPTIMIZE_FLAGS
Evict current process and will continue executing from the same point the next time is scheduled.
virtual bool onKill()
Definition: Process.h:327
Process(unsigned short capacity=0)
constructor
virtual void reset()
Sets process in init state.
bool getDead() const
void pause()
pause execution until wakeup called onPause is called in order children can do custom behaviour
ProcessScheduler *const getProcessScheduler() const
Gets ProcessScheduler which holds this Process.
Definition: Process.h:348
EProcessState
Definition: Process.h:114
@ PREPARED
Process created but not executed.
Definition: Process.h:115
@ TRYING_TO_KILL
sending kill signal but no accepted yet
Definition: Process.h:120
@ INITIATED
executing process normally
Definition: Process.h:116
@ ASLEEP
sleeping. Waiting for a wakeup
Definition: Process.h:117
uint64_t getLastUpdateTime() const
Definition: Process.h:372
virtual void onPause()
Called when a process is paused.
Definition: Process.h:331
void setProcessScheduler(ProcessScheduler *const mgr)
Sets ProcessScheduler which holds this process. Each process can only be scheduled by one ProcessSche...
virtual void killDone()
Definition: Process.h:340
void kill(bool force=false)
Mark this process to be eliminated by the process manager.
static ESwitchResult sleep() OPTIMIZE_FLAGS
pause current process. To reactivate you must use wakeUp
unsigned int getPeriod() const
get period (milliseconds)
Definition: Process.h:360
void setPeriod(unsigned int value)
Set the period for this process.
Definition: Process.h:345
unsigned int getElapsedTime() const
static ESwitchResult waitAndDo(unsigned int msegs, F postWait) OPTIMIZE_FLAGS
Wait for a given time and execute given callable.
Definition: Process.h:380
ESwitchResult
Reason why the process returns from context switch.
Definition: Process.h:127
static ESwitchResult wait(unsigned int msegs) OPTIMIZE_FLAGS
Definition: ProcessScheduler.h:59
Definition: Callback_Impl.h:11
Definition: binary.h:9