×

Discussion Board

Results 1 to 4 of 4
  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    110

    Question Need help with passing data between threads

    I am creating one .exe file with thread support in SDK3 FP1_4. I am trying to pass writable static data between threads . The problem is with all this I cannot see my value of iUrl within thread scope to be NULL . Please help with this . I am getting confused .

    Code:
    //  Include Files  
    
    #include "PThread.h"
    #include <e32base.h>
    #include <e32std.h>
    #include <e32cons.h>			// Console
    #include "MyThread.h"
    #include <e32svr.h>
    //#include <eikenv.h>
    
    //  Constants
    
    _LIT(KTextConsoleTitle, "Console");
    _LIT(KTextFailed, " failed, leave code = %d");
    _LIT(KTextPressAnyKey, " [press any key]\n");
    #define KUrl _L8("http://www.google.com")
    
    //  Global Variables
    LOCAL_D CConsoleBase* console;  // write all messages to this
    
    
    //  Local Functions
    
    LOCAL_C void MainL()
    	{
    	//
    	// add your program code here, example code below
    	//
    	console->Write(_L("Hello, world!\n"));
    	}
    
    
    LOCAL_C void DoStartL()
    	{
    	// Create active scheduler (to run active objects)
    	CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
    	CleanupStack::PushL(scheduler);
    	CActiveScheduler::Install(scheduler);
    
    	MainL();
    
    	// Delete active scheduler
    	CleanupStack::PopAndDestroy(scheduler);
    	}
    
    
    //  Global Functions
    
    GLDEF_C TInt E32Main()
    	{
    	// Create cleanup stack
    	__UHEAP_MARK;
    	CTrapCleanup* cleanup = CTrapCleanup::New();
    	// Create output console
    	TRAPD(createError, console = Console::NewL(KTextConsoleTitle, 
    
    TSize(KConsFullScreen,KConsFullScreen)));
    	if (createError)
    		return createError;
    
    	// Run application code inside TRAP harness, wait keypress when terminated
    	TRAPD(mainError, DoStartL());
    	if (mainError)
    		console->Printf(KTextFailed, mainError);
    	console->Printf(KTextPressAnyKey);	
    	
    //	console->Getch();
    	TRAPD(err,
    			//Install active scheduler
    	 CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
        CleanupStack::PushL(activeScheduler);
        CActiveScheduler::Install(activeScheduler);
        
        // Call thread class
        //first thread
    	TTimeIntervalMicroSeconds32 time(100);
    	CMyThread *iMyThread = CMyThread::NewLC(*console);	
    	
    	//write into url
    	
    	iMyThread->WriteUrl(KUrl);
    	TBuf<250> iWriteBuf;
    	iWriteBuf.Copy(iMyThread->ReadUrl());
    	console->Write(iWriteBuf);//write for 1st time		
    	iMyThread->ExecuteThread(time);
    	
    	//read from file
    	iMyThread->ReadFile();
    	CleanupStack::PopAndDestroy();
    	iMyThread=NULL;
    	//second thread
    	iMyThread = CMyThread::NewLC(*console);
    	iMyThread->ExecuteThread(time);
    // value not visible within scope	//read from file
    	iMyThread->ReadFile();
    	
    	CleanupStack::PopAndDestroy();
    	// Delete active scheduler
    	console->Write(iWriteBuf); // write for 2nd time
    	console->Getch();
    	CleanupStack::PopAndDestroy(activeScheduler);
    	)
    	if(err!=KErrNone)
    	User::Panic(_L("Program closed due to"),err);
    	
    	delete console;
    	delete cleanup;
    	__UHEAP_MARKEND;
    	return KErrNone;
    	}
    Code:
    const TInt KStackSize = 16384;
    _LIT(KExecThreadBaseName, "CPThread");
    
    
    
    // Global thread id counter for making CMyThread thread names unique.
    // This is achieved by appending counter to the end of thread name and
    // incrementing counter value for next thread.
    // This is writable static data.
    static TInt g_thread_id_counter = 0;
    TInt g_thread_concurrency_counter = 0;
    
    //The following writable static data is being used only to pass into thread 
    //from main program.
    HBufC8*		 iUrl; 
    const TInt KMyTlsHandle = 0x084901b0;//0xC0FFEE; // both value giving equal data
    
    LOCAL_C void GenerateUniqueName(TDes& aResult, CMyThread* aExecutor)
        {
        _LIT(KHexFormat, "_0x%x");
        _LIT(KCounterFormat, "_%d_%d");
        aResult.Copy(KExecThreadBaseName);
        aResult.AppendFormat(KHexFormat, aExecutor);
        g_thread_id_counter++;
        g_thread_concurrency_counter++;
        aResult.AppendFormat(KCounterFormat, g_thread_id_counter,
        		g_thread_concurrency_counter);
        }
     
    CMyThread* CMyThread::NewL(CConsoleBase& aConsole)
        {
        CMyThread* self =CMyThread::NewLC(aConsole);
        CleanupStack::Pop(self);
        return self;
        }
    CMyThread* CMyThread::NewLC(CConsoleBase& aConsole)
    {
    	CMyThread* self = new (ELeave) CMyThread(aConsole);
    	CleanupStack::PushL(self);
    	self->ConstructL();
    	return self;
    }
    CMyThread::CMyThread(CConsoleBase& aConsole)
        : CActive(EPriorityHigh),iConsole(aConsole)
        {    
        }
     
    CMyThread::~CMyThread()
        {
        // When done with the object, delete it and free TLS
    	delete iUrl;
    	iUrl = NULL;
    	UserSvr::DllFreeTls( KMyTlsHandle );
        Cancel();
        iThread.Close();
        }
     
    void CMyThread::ConstructL()
        {
        CActiveScheduler::Add(this);
        iFlagIsBusy=EFalse;
        //Create variable
    	iUrl=  HBufC8::NewL(250);
        //Set handle to static data
    	User::LeaveIfError( UserSvr::DllSetTls( KMyTlsHandle,iUrl));
        }
     
    TInt CMyThread::ExecuteThread(TTimeIntervalMicroSeconds32 anInterval)
        {  
        TInt ret = KErrNone;
        iInterval = anInterval;
        TRAP(ret,CreateThreadL());
        if (!ret)
            {
            ret = StartThread();
            }
        return ret;
        }
     
    TInt CMyThread::StartThread()
        {
        TInt ret = KErrNone;
        if(!IsActive())
            {
            // Requests notification when this thread dies
            // normally or otherwise
            iThread.Logon(iStatus);
            SetActive();
            iThread.Resume();
            }
        else
            {
            ret = KErrOverflow;
            }
        return ret;
        }
     
    void CMyThread::ThreadExecuted(TInt /*aError*/)
        {
        
        }
     
    void CMyThread::RunL()
        {
        ThreadExecuted(iStatus.Int());
        }
     
    void CMyThread::DoCancel()
        {
        iThread.LogonCancel(iStatus);
        iThread.Kill(KErrCancel);
        }
     
    void CMyThread::CreateThreadL()
        {
        HBufC* threadName = HBufC::NewLC(KMaxFileName);
        TPtr ptr = threadName->Des();
        GenerateUniqueName(ptr, this);
     
        User::LeaveIfError(iThread.Create(
                            *threadName,
                            CMyThread::ThreadFunction,/*name of callback*/
                            KStackSize,/*creating new stack*/
                            NULL,/*sharing heap*/
                            this/* passes this class as an argument to the thread 
    
    function*/));
      
        CleanupStack::PopAndDestroy(threadName);
        }
     
    /*Every thing inside this function including function call is being executed 
     * inside the thread */
    TInt CMyThread::ThreadFunction(TAny* aParams)
        {
        // 1. Add cleanup stack support.
        CTrapCleanup* cleanupStack = CTrapCleanup::New();
     
        // 2. Get pointer to thread host
        CMyThread* host = (CMyThread*)aParams;
        
        TRAPD(err,
            // 3. Add support for active objects
            CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
            CleanupStack::PushL(activeScheduler);
            CActiveScheduler::Install(activeScheduler);
     
            // 4. Create and start CPeriodic class that is executed in this thread
            CPeriodic* periodic = CPeriodic::NewL(CActive::EPriorityLow);
            CleanupStack::PushL(periodic);
            periodic->Start(host->Interval(),host->Interval(),
            TCallBack(host->PeriodicTick, host));
           
            // 5. Write a string in a File
         //   host->WriteFile(*host);// this is never called if uncommented 
              host->WriteFile();// this one does
            // 6. --> Thread execution starts
              host->iFlagIsBusy=ETrue;  
            CActiveScheduler::Start();
            
            // 7. --> Thread execution ends (waiting for CActiveScheduler::Stop())
     
            CleanupStack::PopAndDestroy(periodic);
            CleanupStack::PopAndDestroy(activeScheduler);
            );
        	
        host->ThreadExecuted(err);
        delete cleanupStack;
        return KErrNone;
        }
    
    void  CMyThread::WriteFile()
    	{
    	_LIT(KFileName,"c:\\WriteFile.dat");
        _LIT8(KWriteString,"- into thread successfully");
       TInt FileErr;
       RFs Fs;
       TBuf8<100> iBuf;
       Fs.Connect();
       RFile ResponseFile; 
       FileErr=ResponseFile.Open(Fs,KFileName,EFileWrite);
       if(FileErr!=KErrNone)
    	   FileErr= ResponseFile.Create(Fs,KFileName,EFileWrite);
       if(FileErr==KErrNone){
    	   		iBuf.Copy(RThread().FullName());
    	   		iBuf.Append(KWriteString);
    	   		ResponseFile.Write(iBuf);
    //	   		ResponseFile.Flush();
    	   		
    	   		// Get the object from TLS
    //no value
    	   		iUrl = static_cast<HBufC8*>( UserSvr::DllTls( KMyTlsHandle ) ); 
    //no value
    	   		
    	   		ResponseFile.Write(iBuf.Length(),iUrl->Des());
    	   		ResponseFile.Flush();
    	   }
       ResponseFile.Close();
       iFlagIsBusy=EFalse;  
       CActiveScheduler::Stop();
          Fs.Close();
    	}
    void  CMyThread::WriteUrl(TPtrC8 aUrl)
    	{
    	iUrl->Des().Copy(aUrl);
    	}
    
    TPtrC8  CMyThread::ReadUrl()
    	{
    	return iUrl->Des();
    	}
    void  CMyThread::ReadFile()
    	{
    	 _LIT(KFileName,"c:\\WriteFile.dat");
        TInt FileErr;
        RFs Fs;
        RFile File;
        TBuf8<100> iBuf;
        //Read from file
        Fs.Connect();
        FileErr=File.Open(Fs,KFileName,EFileRead);
        if(FileErr==KErrNone) 
     	File.Read(iBuf); 
        File.Close();
        Fs.Close();
        //write to console
        TBuf<100>  iWriteBuf;
        iWriteBuf.Copy(iBuf);
        iConsole.Write(iWriteBuf);
        
    	}
    
    TInt CMyThread::PeriodicTick(TAny* aObject)
        {
        CMyThread* mythread = (CMyThread*)aObject;
        if (mythread)
            {       
            // Thread is executed once so time to stop it only after file write
    //        mythread->ReadParam();
    //        CActiveScheduler::Stop();
            // After this execution continues from CActiveScheduler::Start()
            }
        // Does not continue again 
        // Note: Does not work with this CPeriodic class
        return EFalse; 
        }

  2. #2
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,567

    Re: Need help with passing data between threads

    Decide what you want:
    - writable static is not nice, but accessible from anywhere
    - TLS is Thread Local Storage, so it is purposedly maintained on a per-thread basis.

  3. #3
    Nokia Developer Champion
    Join Date
    Jul 2004
    Posts
    2,015

    Re: Need help with passing data between threads

    But to take a step backwards first, as always when mixing threads and active objects, the question to ask is must you use threads? Do you need pre-emptive scheduling? If not, life is easier without threads.

  4. #4
    Registered User
    Join Date
    Sep 2008
    Posts
    110

    Re: Need help with passing data between threads

    OK I needed to implement TLS here . Its only that I started with WSD and it didnot work out so I was trying the next solution .. Everey where I am looking for TLS is related to a .dll , but my code is a console based .exe .
    Last edited by sudeepa2005; 2009-05-26 at 07:51.

Similar Threads

  1. Replies: 2
    Last Post: 2008-07-03, 15:29
  2. Replies: 1
    Last Post: 2008-05-12, 16:07
  3. message passing between threads
    By mayankkedia in forum Symbian C++
    Replies: 2
    Last Post: 2004-09-03, 04:27
  4. Problems with client/server data transfer
    By wilse in forum Symbian C++
    Replies: 1
    Last Post: 2004-08-03, 16:14
  5. passing data to another application.
    By prbhat in forum Symbian User Interface
    Replies: 1
    Last Post: 2002-11-27, 13:15

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •