PTLib
Version 2.10.4
|
00001 /* 00002 * pprocess.h 00003 * 00004 * Operating System Process (running program executable) class. 00005 * 00006 * Portable Windows Library 00007 * 00008 * Copyright (c) 1993-1998 Equivalence Pty. Ltd. 00009 * 00010 * The contents of this file are subject to the Mozilla Public License 00011 * Version 1.0 (the "License"); you may not use this file except in 00012 * compliance with the License. You may obtain a copy of the License at 00013 * http://www.mozilla.org/MPL/ 00014 * 00015 * Software distributed under the License is distributed on an "AS IS" 00016 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 00017 * the License for the specific language governing rights and limitations 00018 * under the License. 00019 * 00020 * The Original Code is Portable Windows Library. 00021 * 00022 * The Initial Developer of the Original Code is Equivalence Pty. Ltd. 00023 * 00024 * Portions are Copyright (C) 1993 Free Software Foundation, Inc. 00025 * All Rights Reserved. 00026 * 00027 * Contributor(s): ______________________________________. 00028 * 00029 * $Revision: 26758 $ 00030 * $Author: rjongbloed $ 00031 * $Date: 2011-12-06 18:52:22 -0600 (Tue, 06 Dec 2011) $ 00032 */ 00033 00034 #ifndef PTLIB_PROCESS_H 00035 #define PTLIB_PROCESS_H 00036 00037 #ifdef P_USE_PRAGMA 00038 #pragma interface 00039 #endif 00040 00041 #include <ptlib/mutex.h> 00042 #include <ptlib/syncpoint.h> 00043 #include <ptlib/thread.h> 00044 #include <ptlib/pfactory.h> 00045 00046 #include <queue> 00047 #include <set> 00048 00055 #ifdef P_VXWORKS 00056 #define PCREATE_PROCESS(cls) \ 00057 cls instance; \ 00058 instance.InternalMain(); 00059 #elif defined(P_RTEMS) 00060 #define PCREATE_PROCESS(cls) \ 00061 extern "C" {\ 00062 void* POSIX_Init( void* argument) \ 00063 { \ 00064 static cls instance; \ 00065 exit( instance.InternalMain() ); \ 00066 } \ 00067 } 00068 #elif defined(_WIN32_WCE) 00069 #define PCREATE_PROCESS(cls) \ 00070 PDEFINE_WINMAIN(hInstance, , lpCmdLine, ) \ 00071 { \ 00072 cls *pInstance = new cls(); \ 00073 pInstance->GetArguments().SetArgs(lpCmdLine); \ 00074 int terminationValue = pInstance->InternalMain(hInstance); \ 00075 delete pInstance; \ 00076 return terminationValue; \ 00077 } 00078 #else 00079 #define PCREATE_PROCESS(cls) \ 00080 int main(int argc, char ** argv, char ** envp) \ 00081 { \ 00082 cls *pInstance = new cls(); \ 00083 pInstance->PreInitialise(argc, argv, envp); \ 00084 int terminationValue = pInstance->InternalMain(); \ 00085 delete pInstance; \ 00086 return terminationValue; \ 00087 } 00088 #endif // P_VXWORKS 00089 00090 /*$MACRO PDECLARE_PROCESS(cls,ancestor,manuf,name,major,minor,status,build) 00091 This macro is used to declare the components necessary for a user PWLib 00092 process. This will declare the PProcess descendent class, eg PApplication, 00093 and create an instance of the class. See the <code>PCREATE_PROCESS</code> macro 00094 for more details. 00095 */ 00096 #define PDECLARE_PROCESS(cls,ancestor,manuf,name,major,minor,status,build) \ 00097 class cls : public ancestor { \ 00098 PCLASSINFO(cls, ancestor); \ 00099 public: \ 00100 cls() : ancestor(manuf, name, major, minor, status, build) { } \ 00101 private: \ 00102 virtual void Main(); \ 00103 }; 00104 00105 00106 class PTimerList : public PObject 00107 /* This class defines a list of <code>PTimer</code> objects. It is primarily used 00108 internally by the library and the user should never create an instance of 00109 it. The <code>PProcess</code> instance for the application maintains an instance 00110 of all of the timers created so that it may decrements them at regular 00111 intervals. 00112 */ 00113 { 00114 PCLASSINFO(PTimerList, PObject); 00115 00116 public: 00117 // Create a new timer list 00118 PTimerList(); 00119 00120 /* Decrement all the created timers and dispatch to their callback 00121 functions if they have expired. The <code>PTimer::Tick()</code> function 00122 value is used to determine the time elapsed since the last call to 00123 Process(). 00124 00125 The return value is the number of milliseconds until the next timer 00126 needs to be despatched. The function need not be called again for this 00127 amount of time, though it can (and usually is). 00128 00129 @return 00130 maximum time interval before function should be called again. 00131 */ 00132 PTimeInterval Process(); 00133 00134 PTimer::IDType GetNewTimerId() const { return ++timerId; } 00135 00136 class RequestType { 00137 public: 00138 enum Action { 00139 Stop, 00140 Start 00141 } m_action; 00142 00143 RequestType(Action act, PTimer * t) 00144 : m_action(act) 00145 , m_timer(t) 00146 , m_id(t->GetTimerId()) 00147 , m_absoluteTime(t->GetAbsoluteTime()) 00148 , m_serialNumber(t->GetNextSerialNumber()) 00149 , m_sync(NULL) 00150 { } 00151 00152 PTimer * m_timer; 00153 PTimer::IDType m_id; 00154 PInt64 m_absoluteTime; 00155 PAtomicInteger::IntegerType m_serialNumber; 00156 PSyncPoint * m_sync; 00157 }; 00158 00159 void QueueRequest(RequestType::Action action, PTimer * timer, bool isSync = true); 00160 00161 void ProcessTimerQueue(); 00162 00163 private: 00164 // queue of timer action requests 00165 PMutex m_queueMutex; 00166 typedef std::queue<RequestType> RequestQueueType; 00167 RequestQueueType m_requestQueue; 00168 00169 // add an active timer to the lists 00170 void AddActiveTimer(const RequestType & request); 00171 00172 // counter to keep track of timer IDs 00173 mutable PAtomicInteger timerId; 00174 00175 // map used to store active timer information 00176 struct ActiveTimerInfo { 00177 ActiveTimerInfo(PTimer * t, PAtomicInteger::IntegerType serialNumber) 00178 : m_timer(t), m_serialNumber(serialNumber) { } 00179 PTimer * m_timer; 00180 PAtomicInteger::IntegerType m_serialNumber; 00181 }; 00182 typedef std::map<PTimer::IDType, ActiveTimerInfo> ActiveTimerInfoMap; 00183 ActiveTimerInfoMap m_activeTimers; 00184 00185 // set used to store timer expiry times, in order 00186 struct TimerExpiryInfo { 00187 TimerExpiryInfo(PTimer::IDType id, PInt64 expireTime, PAtomicInteger::IntegerType serialNumber) 00188 : m_timerId(id), m_expireTime(expireTime), m_serialNumber(serialNumber) { } 00189 PTimer::IDType m_timerId; 00190 PInt64 m_expireTime; 00191 PAtomicInteger::IntegerType m_serialNumber; 00192 }; 00193 00194 struct TimerExpiryInfo_compare 00195 : public binary_function<TimerExpiryInfo, TimerExpiryInfo, bool> 00196 { 00197 bool operator()(const TimerExpiryInfo & _Left, const TimerExpiryInfo & _Right) const 00198 { return (_Left.m_expireTime < _Right.m_expireTime); } 00199 }; 00200 00201 typedef std::multiset<TimerExpiryInfo, TimerExpiryInfo_compare> TimerExpiryInfoList; 00202 TimerExpiryInfoList m_expiryList; 00203 00204 // The last system timer tick value that was used to process timers. 00205 PTimeInterval m_lastSample; 00206 00207 // thread that handles the timer stuff 00208 PThread * m_timerThread; 00209 }; 00210 00211 00213 // PProcess 00214 00227 class PProcess : public PThread 00228 { 00229 PCLASSINFO(PProcess, PThread); 00230 00231 public: 00234 00235 enum CodeStatus { 00237 AlphaCode, 00239 BetaCode, 00241 ReleaseCode, 00242 NumCodeStatuses 00243 }; 00244 00247 PProcess( 00248 const char * manuf = "", 00249 const char * name = "", 00250 WORD majorVersion = 1, 00251 WORD minorVersion = 0, 00252 CodeStatus status = ReleaseCode, 00253 WORD buildNumber = 1, 00254 bool library = false 00255 ); 00257 00266 Comparison Compare( 00267 const PObject & obj 00268 ) const; 00270 00275 virtual void Terminate(); 00276 00282 virtual PString GetThreadName() const; 00283 00289 virtual void SetThreadName( 00290 const PString & name 00291 ); 00293 00302 static PProcess & Current(); 00303 00307 virtual void OnThreadStart( 00308 PThread & thread 00309 ); 00310 00314 virtual void OnThreadEnded( 00315 PThread & thread 00316 ); 00317 00330 virtual bool OnInterrupt( 00331 bool terminating 00332 ); 00333 00340 static PBoolean IsInitialised(); 00341 00348 void SetTerminationValue( 00349 int value 00350 ); 00351 00361 int GetTerminationValue() const; 00362 00369 PArgList & GetArguments(); 00370 00380 virtual const PString & GetManufacturer() const; 00381 00391 virtual const PString & GetName() const; 00392 00407 virtual PString GetVersion( 00408 PBoolean full = true 00409 ) const; 00410 00416 const PFilePath & GetFile() const; 00417 00425 DWORD GetProcessID() const; 00426 00429 PTime GetStartTime() const; 00430 00439 PString GetUserName() const; 00440 00463 PBoolean SetUserName( 00464 const PString & username, 00465 PBoolean permanent = false 00466 ); 00467 00476 PString GetGroupName() const; 00477 00502 PBoolean SetGroupName( 00503 const PString & groupname, 00504 PBoolean permanent = false 00505 ); 00506 00513 int GetMaxHandles() const; 00514 00524 PBoolean SetMaxHandles( 00525 int newLimit 00526 ); 00527 00528 #ifdef P_CONFIG_FILE 00529 00531 virtual PString GetConfigurationFile(); 00532 #endif 00533 00547 void SetConfigurationPath( 00548 const PString & path 00549 ); 00551 00560 static PString GetOSClass(); 00561 00568 static PString GetOSName(); 00569 00575 static PString GetOSHardware(); 00576 00583 static PString GetOSVersion(); 00584 00590 static bool IsOSVersion( 00591 unsigned major, 00592 unsigned minor = 0, 00593 unsigned build = 0 00594 ); 00595 00603 static PDirectory GetOSConfigDir(); 00604 00611 static PString GetLibVersion(); 00613 00620 PTimerList * GetTimerList(); 00621 00625 void PreInitialise( 00626 int argc, // Number of program arguments. 00627 char ** argv, // Array of strings for program arguments. 00628 char ** envp // Array of string for the system environment 00629 ); 00630 00634 static void PreShutdown(); 00635 static void PostShutdown(); 00636 00638 virtual int InternalMain(void * arg = NULL); 00639 00661 class HostSystemURLHandlerInfo 00662 { 00663 public: 00664 HostSystemURLHandlerInfo() 00665 { } 00666 00667 HostSystemURLHandlerInfo(const PString & t) 00668 : type(t) 00669 { } 00670 00671 static bool RegisterTypes(const PString & types, bool force = true); 00672 00673 void SetIcon(const PString & icon); 00674 PString GetIcon() const; 00675 00676 void SetCommand(const PString & key, const PString & command); 00677 PString GetCommand(const PString & key) const; 00678 00679 bool GetFromSystem(); 00680 bool CheckIfRegistered(); 00681 00682 bool Register(); 00683 00684 PString type; 00685 00686 #if _WIN32 00687 PString iconFileName; 00688 PStringToString cmds; 00689 #endif 00690 }; 00692 00693 protected: 00694 void Construct(); 00695 00696 // Member variables 00697 int terminationValue; 00698 // Application return value 00699 00700 PString manufacturer; 00701 // Application manufacturer name. 00702 00703 PString productName; 00704 // Application executable base name from argv[0] 00705 00706 WORD majorVersion; 00707 // Major version number of the product 00708 00709 WORD minorVersion; 00710 // Minor version number of the product 00711 00712 CodeStatus status; 00713 // Development status of the product 00714 00715 WORD buildNumber; 00716 // Build number of the product 00717 00718 PFilePath executableFile; 00719 // Application executable file from argv[0] (not open) 00720 00721 PStringArray configurationPaths; 00722 // Explicit file or set of directories to find default PConfig 00723 00724 PArgList arguments; 00725 // The list of arguments 00726 00727 PTimerList timers; 00728 // List of active timers in system 00729 00730 PTime programStartTime; 00731 // time at which process was intantiated, i.e. started 00732 00733 int maxHandles; 00734 // Maximum number of file handles process can open. 00735 00736 bool m_library; 00737 00738 bool m_shuttingDown; 00739 00740 typedef std::map<PThreadIdentifier, PThread *> ThreadMap; 00741 ThreadMap m_activeThreads; 00742 PMutex m_activeThreadMutex; 00743 00744 friend class PThread; 00745 00746 00747 // Include platform dependent part of class 00748 #ifdef _WIN32 00749 #include "msos/ptlib/pprocess.h" 00750 #else 00751 #include "unix/ptlib/pprocess.h" 00752 #endif 00753 }; 00754 00755 00758 class PLibraryProcess : public PProcess 00759 { 00760 PCLASSINFO(PLibraryProcess, PProcess); 00761 00762 public: 00767 PLibraryProcess( 00768 const char * manuf = "", 00769 const char * name = "", 00770 WORD majorVersionNum = 1, 00771 WORD minorVersionNum = 0, 00772 CodeStatus statusCode = ReleaseCode, 00773 WORD buildNum = 1 00774 ) : PProcess(manuf, name, majorVersionNum, minorVersionNum, statusCode, buildNum, true) { } 00776 00778 virtual void Main() { } 00779 }; 00780 00781 00782 /* 00783 * one instance of this class (or any descendants) will be instantiated 00784 * via PGenericFactory<PProessStartup> one "main" has been started, and then 00785 * the OnStartup() function will be called. The OnShutdown function will 00786 * be called after main exits, and the instances will be destroyed if they 00787 * are not singletons 00788 */ 00789 class PProcessStartup : public PObject 00790 { 00791 PCLASSINFO(PProcessStartup, PObject) 00792 public: 00793 virtual void OnStartup() { } 00794 virtual void OnShutdown() { } 00795 }; 00796 00797 typedef PFactory<PProcessStartup> PProcessStartupFactory; 00798 00799 #if PTRACING 00800 00801 // using an inline definition rather than a #define crashes gcc 2.95. Go figure 00802 #define P_DEFAULT_TRACE_OPTIONS ( PTrace::Blocks | PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine ) 00803 00804 template <unsigned level, unsigned options = P_DEFAULT_TRACE_OPTIONS > 00805 class PTraceLevelSetStartup : public PProcessStartup 00806 { 00807 public: 00808 void OnStartup() 00809 { PTrace::Initialise(level, NULL, options); } 00810 }; 00811 00812 #endif // PTRACING 00813 00814 00815 #endif // PTLIB_PROCESS_H 00816 00817 00818 // End Of File ///////////////////////////////////////////////////////////////