1 /* 2 * lftp - file transfer program 3 * 4 * Copyright (c) 1996-2016 by Alexander V. Lukyanov (lav@yars.free.net) 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef SMTASK_H 21 #define SMTASK_H 22 23 #include "PollVec.h" 24 #include "TimeDate.h" 25 #include "Ref.h" 26 #include "xarray.h" 27 #include "xlist.h" 28 #include "misc.h" 29 #include "Error.h" 30 #include <errno.h> 31 32 class SMTask 33 { 34 virtual int Do() = 0; 35 36 // all tasks list 37 static xlist_head<SMTask> all_tasks; 38 xlist<SMTask> all_tasks_node; 39 40 // ready (not suspended) tasks list 41 static xlist_head<SMTask> ready_tasks; 42 xlist<SMTask> ready_tasks_node; 43 44 // just created or resumed tasks 45 static xlist_head<SMTask> new_tasks; 46 xlist<SMTask> new_tasks_node; 47 48 // deleted and going to be destroyed tasks 49 static xlist_head<SMTask> deleted_tasks; 50 xlist<SMTask> deleted_tasks_node; 51 52 static PollVec block; 53 enum { SMTASK_MAX_DEPTH=64 }; 54 static SMTask *stack[SMTASK_MAX_DEPTH]; 55 static int stack_ptr; 56 57 bool suspended; 58 bool suspended_slave; 59 60 int running; 61 int ref_count; 62 bool deleting; 63 64 int ScheduleThis(); 65 static int ScheduleNew(); 66 67 protected: 68 enum 69 { 70 STALL=0, 71 MOVED=1, // STALL|MOVED==MOVED. 72 WANTDIE=2 // for AcceptSig 73 }; 74 75 // SuspendInternal and ResumeInternal usually suspend and resume slave tasks SuspendInternal()76 virtual void SuspendInternal() {} 77 virtual void ResumeInternal(); PrepareToDie()78 virtual void PrepareToDie() {} // it is called from Delete no matter of running and ref_count 79 Deleted()80 bool Deleted() const { return deleting; } 81 virtual ~SMTask(); 82 83 public: Block(int fd,int mask)84 static void Block(int fd,int mask) { block.AddFD(fd,mask); } TimeoutU(int us)85 static void TimeoutU(int us) { block.AddTimeoutU(us); } Timeout(int ms)86 static void Timeout(int ms) { TimeoutU(1000*ms); } TimeoutS(int s)87 static void TimeoutS(int s) { TimeoutU(1000000*s); } Ready(int fd,int mask)88 static bool Ready(int fd,int mask) { return block.FDReady(fd,mask); } SetNotReady(int fd,int mask)89 static void SetNotReady(int fd,int mask) { block.FDSetNotReady(fd,mask); } 90 91 static TimeDate now; UpdateNow()92 static void UpdateNow() { now.SetToCurrentTime(); } 93 94 static void Schedule(); 95 static int CollectGarbage(); 96 static void Block(); 97 static time_t last_block; 98 99 void Suspend(); 100 void Resume(); 101 102 // SuspendSlave and ResumeSlave are used in SuspendInternal/ResumeInternal 103 // to suspend/resume slave tasks 104 void SuspendSlave(); 105 void ResumeSlave(); 106 IsSuspended()107 bool IsSuspended() { return suspended|suspended_slave; } 108 GetLogContext()109 virtual const char *GetLogContext() { return 0; } GetCurrentLogContext()110 static const char *GetCurrentLogContext() { return current->GetLogContext(); } 111 112 SMTask(); 113 114 void DeleteLater(); 115 static void Delete(SMTask *); IncRefCount()116 void IncRefCount() { ref_count++; } DecRefCount()117 void DecRefCount() { if(ref_count>0) ref_count--; } _MakeRef(SMTask * task)118 static SMTask *_MakeRef(SMTask *task) { if(task) task->IncRefCount(); return task; } _DeleteRef(SMTask * task)119 static void _DeleteRef(SMTask *task) { if(task) { task->DecRefCount(); Delete(task); } } 120 static SMTask *_SetRef(SMTask *task,SMTask *new_task); MakeRef(T * task)121 template<typename T> static T *MakeRef(T *task) { _MakeRef(task); return task; } 122 static int Roll(SMTask *); Roll()123 int Roll() { return Roll(this); } 124 static void RollAll(const TimeInterval &max_time); 125 126 static SMTask *current; 127 128 static void Enter(SMTask *task); 129 static void Leave(SMTask *task); Enter()130 void Enter() { Enter(this); } Leave()131 void Leave() { Leave(this); } 132 133 static int TaskCount(); 134 static void PrintTasks(); 135 static bool NonFatalError(int err); TemporaryNetworkError(int err)136 static bool TemporaryNetworkError(int err) { return temporary_network_error(err); } 137 static Error *SysError(int e=errno) { return new Error(e,strerror(e),!NonFatalError(e)); } 138 139 static void Cleanup(); 140 }; 141 142 class SMTaskInit : public SMTask 143 { 144 int Do(); 145 public: 146 SMTaskInit(); 147 ~SMTaskInit(); 148 }; 149 150 template<class T> class SMTaskRef 151 { 152 SMTaskRef<T>(const SMTaskRef<T>&); // disable cloning 153 void operator=(const SMTaskRef<T>&); // and assignment 154 155 protected: 156 T *ptr; 157 158 public: SMTaskRef()159 SMTaskRef() { ptr=0; } ptr(SMTask::MakeRef (p))160 SMTaskRef<T>(T *p) : ptr(SMTask::MakeRef(p)) {} 161 ~SMTaskRef<T>() { SMTask::_DeleteRef(ptr); ptr=0; } 162 void operator=(T *p) { ptr=static_cast<T*>(SMTask::_SetRef(ptr,p)); } 163 operator const T*() const { return ptr; } 164 T *operator->() const { return ptr; } borrow()165 T *borrow() { if(ptr) ptr->DecRefCount(); return replace_value(ptr,(T*)0); } get()166 const T *get() const { return ptr; } get_non_const()167 T *get_non_const() const { return ptr; } 168 Cast()169 template<class C> const SMTaskRef<C>& Cast() const 170 { void(static_cast<C*>(ptr)); return *(const SMTaskRef<C>*)this; } 171 172 static const SMTaskRef<T> null; 173 _set(T * p)174 void _set(T *p) { ptr=p; } _clear()175 void _clear() { ptr=0; } unset()176 void unset() { *this=0; } 177 }; 178 179 template<typename T> 180 class TaskRefArray : public _RefArray< T,SMTaskRef<T> > { 181 TaskRefArray& operator=(const TaskRefArray&); // make assignment fail 182 TaskRefArray(const TaskRefArray&); // disable cloning 183 public: TaskRefArray()184 TaskRefArray() : _RefArray< T,SMTaskRef<T> >() {} 185 }; 186 187 #endif /* SMTASK_H */ 188