examples/Base/IPC/AdvancedClientServerExample/ThreadServer/src/threadserver.cpp

00001 /*
00002 Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:  
00028 */
00029 
00030 
00031 #include "threadserver.h"
00032 #include "threadserverstart.h"
00033 #include "threadserversession.h"
00034 
00035 const TInt KThreadServerShutDownDelay = 50000000; //50 sec
00036 
00037 
00038 //******CThreadServer******//
00042 void CThreadServer::NewLC()
00043         {
00044         CThreadServer* s = new(ELeave) CThreadServer();
00045         CleanupStack::PushL(s);
00046         s->ConstructL();
00047         }
00051 CThreadServer::CThreadServer()
00052         :CServer2(EPriorityStandard, ESharableSessions),iDriverState(EStateUnknown)
00053         {
00054         }
00055 void CThreadServer::ConstructL()
00056         {
00057         // Call CServer2::StartL() before any other functions inside ConstructL
00058         // to avoid errors other than KErrAlreadyExists when the duplicate Server starts
00059         StartL(KThreadServerName);
00060         iDelayThreadServerShutDown = CDelayServerShutDown::NewL();
00061         }
00065 CThreadServer::~CThreadServer()
00066         {
00067         if (iDelayThreadServerShutDown)
00068                 {
00069                 iDelayThreadServerShutDown->Cancel();
00070                 delete iDelayThreadServerShutDown;
00071                 }
00072         // unload device driver when server terminated
00073         UnloadDevice();
00074         }
00081 CSession2* CThreadServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
00082         {
00083         //check whether version is compatible
00084         TVersion v(KThreadServerVersion,KThreadServerMinorVersionNumber,KThreadServerBuildVersionNumber);
00085         if(!User::QueryVersionSupported(v, aVersion))
00086                 User::Leave(KErrNotSupported);
00087 
00088         // construct and return the server side client session object
00089         CThreadServer& ncThis = const_cast<CThreadServer&>(*this);
00090         CThreadServerSession* serverSession = CThreadServerSession::NewL(ncThis);
00091         return serverSession;
00092         }
00096 void CThreadServer::IncrementRefCount()
00097         {
00098         iRefCount++;
00099         iDelayThreadServerShutDown->Cancel(); // Cancel shutdown if it has started due to no clients being connected.
00100         }
00104 void CThreadServer::DecrementRefCount() 
00105         {
00106         iRefCount--;
00107         if ( iRefCount == 0 )
00108                 {
00109                 iDelayThreadServerShutDown->SetDelay(TTimeIntervalMicroSeconds32(KThreadServerShutDownDelay));
00110                 }
00111         }
00115 void CThreadServer::RenameServer()
00116         {
00117         //Rename thread server name in order to prevent same name creation
00118         RThread serverThread;
00119         TThreadId threadId;
00120         TName name;
00121         name.Append(KThreadServerName); 
00122         threadId = serverThread.Id();
00123         name.AppendNum(threadId.Id(),EHex);
00124         //We are ignoring the error code returned from User::RenameThread
00125         //as it is not important here, it may be used for profiling
00126         User::RenameThread(name);
00127         }
00132 TInt CThreadServer::LoadDevice()
00133         {
00134         if (iDriverState>=EDriverLoaded && iDriverState<EDriverUnloaded)
00135                 return KErrNone; //Device has been loaded, return immediately
00136                 
00137         TInt r=User::LoadPhysicalDevice(KThreadServerDriverPddFileName);
00138         if (r!=KErrNone && r!=KErrAlreadyExists)
00139                 return r; //some error occurred
00140         
00141         r = User::LoadLogicalDevice(KThreadServerDriverLddFileName);
00142         if (r!=KErrNone && r!=KErrAlreadyExists)
00143                 return r; //some error occurred 
00144         
00145         //both PDD and LDD have been loaded
00146         UpdateDriverState(EDriverLoaded);
00147         return KErrNone; 
00148         }
00153 TInt CThreadServer::UnloadDevice()
00154         {
00155         if (iDriverState==EDriverUnloaded || iDriverState == EStateUnknown)
00156                 return KErrNone; //no device is loaded, return immediately
00157                 
00158         // close device
00159         if (iDriver.Handle())
00160                 iDriver.Close();
00161         // Unload Logical Device
00162         TInt r = User::FreeLogicalDevice(RDriver1::Name());
00163         if (r!=KErrNone)
00164                 return r;
00165         // Unload Physical Device
00166         TName pddName(RDriver1::Name());
00167         _LIT(KVariantExtension,".template");
00168         pddName.Append(KVariantExtension);
00169         r=User::FreePhysicalDevice(pddName);
00170         
00171         if (KErrNone==r)
00172                 UpdateDriverState(EDriverUnloaded);     
00173         return r;
00174         }
00179 TInt CThreadServer::OpenLogicalChannel()
00180         {
00181         if (iDriverState>=ELogicalChannelOpened && iDriverState<ELogicalChannelClosed)
00182                 return KErrNone;
00183         
00184         TInt r = iDriver.Open();
00185         if (KErrNone==r)
00186                 UpdateDriverState(ELogicalChannelOpened);
00187         
00188         return r;
00189         }
00193 void CThreadServer::CloseLogicalChannel()
00194         {
00195         if (iDriver.Handle())
00196                 {
00197                 iDriver.Close();
00198                 UpdateDriverState(ELogicalChannelClosed);
00199                 }
00200         }
00207 TInt CThreadServer::SendDataToDevice(TRequestStatus& aStatus, const TDesC8& aData)
00208         {
00209         TInt r = KErrNone;
00210         if (iDriverState>=ELogicalChannelOpened && iDriverState<ELogicalChannelClosed)
00211                 {
00212                 iDriver.SendData(aStatus, aData);
00213                 UpdateDriverState(ESendingData);
00214                 }
00215         else
00216                 {
00217                 r = KErrArgument;
00218                 }
00219         return r;
00220         }
00224 void CThreadServer::CancelSendData()
00225         {
00226         iDriver.SendDataCancel();
00227         UpdateDriverState(ELogicalChannelOpened);
00228         }
00233 void CThreadServer::UpdateDriverState(TDriverState aState)
00234         {
00235         iDriverState = aState;
00236         }
00237 //EOF

Generated by  doxygen 1.6.2