Blame src/SMTask.h

Packit 8f70b4
/*
Packit 8f70b4
 * lftp - file transfer program
Packit 8f70b4
 *
Packit 8f70b4
 * Copyright (c) 1996-2016 by Alexander V. Lukyanov (lav@yars.free.net)
Packit 8f70b4
 *
Packit 8f70b4
 * This program is free software; you can redistribute it and/or modify
Packit 8f70b4
 * it under the terms of the GNU General Public License as published by
Packit 8f70b4
 * the Free Software Foundation; either version 3 of the License, or
Packit 8f70b4
 * (at your option) any later version.
Packit 8f70b4
 *
Packit 8f70b4
 * This program is distributed in the hope that it will be useful,
Packit 8f70b4
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
 * GNU General Public License for more details.
Packit 8f70b4
 *
Packit 8f70b4
 * You should have received a copy of the GNU General Public License
Packit 8f70b4
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#ifndef SMTASK_H
Packit 8f70b4
#define SMTASK_H
Packit 8f70b4
Packit 8f70b4
#include "PollVec.h"
Packit 8f70b4
#include "TimeDate.h"
Packit 8f70b4
#include "Ref.h"
Packit 8f70b4
#include "xarray.h"
Packit 8f70b4
#include "xlist.h"
Packit 8f70b4
#include "misc.h"
Packit 8f70b4
#include "Error.h"
Packit 8f70b4
#include <errno.h>
Packit 8f70b4
Packit 8f70b4
class SMTask
Packit 8f70b4
{
Packit 8f70b4
   virtual int Do() = 0;
Packit 8f70b4
Packit 8f70b4
   // all tasks list
Packit 8f70b4
   static xlist_head<SMTask> all_tasks;
Packit 8f70b4
   xlist<SMTask> all_tasks_node;
Packit 8f70b4
Packit 8f70b4
   // ready (not suspended) tasks list
Packit 8f70b4
   static xlist_head<SMTask> ready_tasks;
Packit 8f70b4
   xlist<SMTask> ready_tasks_node;
Packit 8f70b4
Packit 8f70b4
   // just created or resumed tasks
Packit 8f70b4
   static xlist_head<SMTask> new_tasks;
Packit 8f70b4
   xlist<SMTask> new_tasks_node;
Packit 8f70b4
Packit 8f70b4
   // deleted and going to be destroyed tasks
Packit 8f70b4
   static xlist_head<SMTask> deleted_tasks;
Packit 8f70b4
   xlist<SMTask> deleted_tasks_node;
Packit 8f70b4
Packit 8f70b4
   static PollVec block;
Packit 8f70b4
   enum { SMTASK_MAX_DEPTH=64 };
Packit 8f70b4
   static SMTask *stack[SMTASK_MAX_DEPTH];
Packit 8f70b4
   static int stack_ptr;
Packit 8f70b4
Packit 8f70b4
   bool	 suspended;
Packit 8f70b4
   bool	 suspended_slave;
Packit 8f70b4
Packit 8f70b4
   int	 running;
Packit 8f70b4
   int	 ref_count;
Packit 8f70b4
   bool	 deleting;
Packit 8f70b4
Packit 8f70b4
   int ScheduleThis();
Packit 8f70b4
   static int ScheduleNew();
Packit 8f70b4
Packit 8f70b4
protected:
Packit 8f70b4
   enum
Packit 8f70b4
   {
Packit 8f70b4
      STALL=0,
Packit 8f70b4
      MOVED=1,	  // STALL|MOVED==MOVED.
Packit 8f70b4
      WANTDIE=2	  // for AcceptSig
Packit 8f70b4
   };
Packit 8f70b4
Packit 8f70b4
   // SuspendInternal and ResumeInternal usually suspend and resume slave tasks
Packit 8f70b4
   virtual void SuspendInternal() {}
Packit 8f70b4
   virtual void ResumeInternal();
Packit 8f70b4
   virtual void PrepareToDie() {}  // it is called from Delete no matter of running and ref_count
Packit 8f70b4
Packit 8f70b4
   bool Deleted() const { return deleting; }
Packit 8f70b4
   virtual ~SMTask();
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   static void Block(int fd,int mask) { block.AddFD(fd,mask); }
Packit 8f70b4
   static void TimeoutU(int us) { block.AddTimeoutU(us); }
Packit 8f70b4
   static void Timeout(int ms) { TimeoutU(1000*ms); }
Packit 8f70b4
   static void TimeoutS(int s) { TimeoutU(1000000*s); }
Packit 8f70b4
   static bool Ready(int fd,int mask) { return block.FDReady(fd,mask); }
Packit 8f70b4
   static void SetNotReady(int fd,int mask) { block.FDSetNotReady(fd,mask); }
Packit 8f70b4
Packit 8f70b4
   static TimeDate now;
Packit 8f70b4
   static void UpdateNow() { now.SetToCurrentTime(); }
Packit 8f70b4
Packit 8f70b4
   static void Schedule();
Packit 8f70b4
   static int CollectGarbage();
Packit 8f70b4
   static void Block();
Packit 8f70b4
   static time_t last_block;
Packit 8f70b4
Packit 8f70b4
   void Suspend();
Packit 8f70b4
   void Resume();
Packit 8f70b4
Packit 8f70b4
   // SuspendSlave and ResumeSlave are used in SuspendInternal/ResumeInternal
Packit 8f70b4
   // to suspend/resume slave tasks
Packit 8f70b4
   void SuspendSlave();
Packit 8f70b4
   void ResumeSlave();
Packit 8f70b4
Packit 8f70b4
   bool IsSuspended() { return suspended|suspended_slave; }
Packit 8f70b4
Packit 8f70b4
   virtual const char *GetLogContext() { return 0; }
Packit 8f70b4
   static const char *GetCurrentLogContext() { return current->GetLogContext(); }
Packit 8f70b4
Packit 8f70b4
   SMTask();
Packit 8f70b4
Packit 8f70b4
   void DeleteLater();
Packit 8f70b4
   static void Delete(SMTask *);
Packit 8f70b4
   void IncRefCount() { ref_count++; }
Packit 8f70b4
   void DecRefCount() { if(ref_count>0) ref_count--; }
Packit 8f70b4
   static SMTask *_MakeRef(SMTask *task) { if(task) task->IncRefCount(); return task; }
Packit 8f70b4
   static void _DeleteRef(SMTask *task)  { if(task) { task->DecRefCount(); Delete(task); } }
Packit 8f70b4
   static SMTask *_SetRef(SMTask *task,SMTask *new_task);
Packit 8f70b4
   template<typename T> static T *MakeRef(T *task) { _MakeRef(task); return task; }
Packit 8f70b4
   static int Roll(SMTask *);
Packit 8f70b4
   int Roll() { return Roll(this); }
Packit 8f70b4
   static void RollAll(const TimeInterval &max_time);
Packit 8f70b4
Packit 8f70b4
   static SMTask *current;
Packit 8f70b4
Packit 8f70b4
   static void Enter(SMTask *task);
Packit 8f70b4
   static void Leave(SMTask *task);
Packit 8f70b4
   void Enter() { Enter(this); }
Packit 8f70b4
   void Leave() { Leave(this); }
Packit 8f70b4
Packit 8f70b4
   static int TaskCount();
Packit 8f70b4
   static void PrintTasks();
Packit 8f70b4
   static bool NonFatalError(int err);
Packit 8f70b4
   static bool TemporaryNetworkError(int err) { return temporary_network_error(err); }
Packit 8f70b4
   static Error *SysError(int e=errno) { return new Error(e,strerror(e),!NonFatalError(e)); }
Packit 8f70b4
Packit 8f70b4
   static void Cleanup();
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
class SMTaskInit : public SMTask
Packit 8f70b4
{
Packit 8f70b4
   int Do();
Packit 8f70b4
public:
Packit 8f70b4
   SMTaskInit();
Packit 8f70b4
   ~SMTaskInit();
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
template<class T> class SMTaskRef
Packit 8f70b4
{
Packit 8f70b4
   SMTaskRef<T>(const SMTaskRef<T>&);  // disable cloning
Packit 8f70b4
   void operator=(const SMTaskRef<T>&);   // and assignment
Packit 8f70b4
Packit 8f70b4
protected:
Packit 8f70b4
   T *ptr;
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   SMTaskRef() { ptr=0; }
Packit 8f70b4
   SMTaskRef<T>(T *p) : ptr(SMTask::MakeRef(p)) {}
Packit 8f70b4
   ~SMTaskRef<T>() { SMTask::_DeleteRef(ptr); ptr=0; }
Packit 8f70b4
   void operator=(T *p) { ptr=static_cast<T*>(SMTask::_SetRef(ptr,p)); }
Packit 8f70b4
   operator const T*() const { return ptr; }
Packit 8f70b4
   T *operator->() const { return ptr; }
Packit 8f70b4
   T *borrow() { if(ptr) ptr->DecRefCount(); return replace_value(ptr,(T*)0); }
Packit 8f70b4
   const T *get() const { return ptr; }
Packit 8f70b4
   T *get_non_const() const { return ptr; }
Packit 8f70b4
Packit 8f70b4
   template<class C> const SMTaskRef<C>& Cast() const
Packit 8f70b4
      { void(static_cast<C*>(ptr)); return *(const SMTaskRef<C>*)this; }
Packit 8f70b4
Packit 8f70b4
   static const SMTaskRef<T> null;
Packit 8f70b4
Packit 8f70b4
   void _set(T *p) { ptr=p; }
Packit 8f70b4
   void _clear() { ptr=0; }
Packit 8f70b4
   void unset() { *this=0; }
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
template<typename T>
Packit 8f70b4
class TaskRefArray : public _RefArray< T,SMTaskRef<T> > {
Packit 8f70b4
   TaskRefArray& operator=(const TaskRefArray&); // make assignment fail
Packit 8f70b4
   TaskRefArray(const TaskRefArray&);	       // disable cloning
Packit 8f70b4
public:
Packit 8f70b4
   TaskRefArray() : _RefArray< T,SMTaskRef<T> >() {}
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
#endif /* SMTASK_H */