thread synchronization???

T

tat

Hi,

I am not sure that my question is off topic. I, however, hope that
someone can help me or redirect me to an appropriate forum.

I have some functions (native C codes) which compiled into DLL. In
this DLL, there is a file which contains all global variables and a
main function which contains a while loop. Every cycle of the while
loop some global variables are updated. I wrote wrapper of this DLL
using C++/CLI and expose only the main function as well as some global
variables of the native DLL.

In my C# application, I create a background thread. This background
thread will run main function. In the C# application, when I output
the value of the global variables I just get the initialize value. It
seems that the C# app could not access the global variables after it
is updated. The native global variables can be updated from either C#
application or from running native main function. I suspect that when
C# thread runs it does not allow other thread access the native global
variables via the wrapper. Can some one tell me what should I do to
solve this problem?
Some code would be very helpful.

Many thanks,
TAT
 
T

tat

Thanks, Peter. I did not write the old native C code so I can't say
that the global variables aren't marked "volatile". Anyway, here is a
code example
For native code which will be compiled into native DLL. Some usual
files that are generated by Visual Studio are omitted.
********** example for the native C code *************************
***defs.h****
#ifndef __DEFS_H__
#define __DEFS_H__

#define HR1_CH (0)
#define HR2_CH (1)
#define HR3_CH (2)
#define ARRAY_SIZE (5)
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void ao(unsigned char);
__declspec(dllexport) unsigned short bo(unsigned short);
__declspec(dllexport) unsigned short co[ARRAY_SIZE];
__declspec(dllexport) void mainFunction(void);
__declspec(dllexport) void initialize(void);

#ifdef __cplusplus
}
#endif
#endif
*****************************
***** globalData.h ********
*****************************
#ifndef __GLOBALDATA_H__
#define __GLOBALDATA_H__
#define BUF_SIZE 8
volatile long g_MainFunctionCounter;
volatile unsigned char g_ibuf[BUF_SIZE];
volatile unsigned char g_obuf[BUF_SIZE];
volatile int g_RunMain;
#endif // end of __GLOBALDATA_H__
**********************************
*********** ao.c ****************
**********************************
#include <stdio.h>
#include "defs.h"

void ao(unsigned char c)
{
printf("Input char = %c\n", c);
}
*******************************************
****************** bo.c *******************
*******************************************
#include <stdio.h>
#include "defs.h"

unsigned short bo(unsigned short c)
{
printf("Input number = %d\n", c);
return c;
}
*********************************************
**************** initialize.c ***************
*********************************************
#include "defs.h"
#include "globalData.h"

void initialize(void)
{
int i;
g_MainFunctionCounter = 0;
g_RunMain = 0;
for(i = 0; i < BUF_SIZE; i++)
{
g_ibuf = 0;
g_obuf = 0;
}
}
********************************************
********* mainFunction.c ***************
********************************************
#include <stdio.h>
#include "defs.h"
#include "globalData.h"

void mainFunction()
{
initialize();

while(g_RunMain == 1)
{
g_MainFunctionCounter++;
g_obuf[0]++;
g_obuf[1]--;
if (g_obuf[0] > 1000000)
{
g_obuf[0] = 0;
}
if(g_obuf[1] < -1000000)
{
g_obuf[1] = 0;
}
}

}
*******************************************
For managed wrapper
*********************************************
*********** ManagedLibraryDll.h *********
*********************************************
// ManagedLibraryDll.h

#pragma once

using namespace System;

namespace ManagedLibraryDll {

#include "../LibraryDll/defs.h"
#include "../LibraryDll/globalData.h"
public ref class ManagedFunctions
{
// TODO: Add your methods for this class here.
public:
ManagedFunctions();
~ManagedFunctions();
!ManagedFunctions();

property int RunMain
{
int get()
{
return g_RunMain;
}
}
property long MainFunctionCounter
{
long get()
{
return g_MainFunctionCounter;
}
}
void ManagedAo(unsigned char c);
unsigned short ManagedBo(unsigned short a);
void RunMainFunc(void);
void StopMainFunc(void);

unsigned char OutputBuffer(int idx);
unsigned char InputBuffer(int idx);

};
}
********************************************************
*********** ManagedLibraryDll.cpp *****************
********************************************************
// This is the main DLL file.

#include "stdafx.h"
#include "ManagedLibraryDll.h"
namespace ManagedLibraryDll
{
ManagedFunctions::ManagedFunctions()
{
}
ManagedFunctions::~ManagedFunctions() {}
ManagedFunctions::!ManagedFunctions() {}

void ManagedFunctions::ManagedAo(unsigned char c)
{
ao(c);
}

unsigned short ManagedFunctions::ManagedBo(unsigned short a)
{
return bo(a);
}

void ManagedFunctions::RunMainFunc()
{
g_RunMain = 1;
mainFunction();
}

void ManagedFunctions::StopMainFunc()
{
g_RunMain = 0;
}

unsigned char ManagedFunctions::OutputBuffer(int idx)
{
return g_obuf[idx];
}

unsigned char ManagedFunctions::InputBuffer(int idx)
{
return g_ibuf[idx];
}
}
Thanks,
TAT
***********************************************************************
C# application main program.cs
****
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using ManagedLibraryDll;

namespace TestCallManagedDllFromCsharp
{
class Program
{
static ManagedFunctions test = new ManagedFunctions();
static Thread th;
static bool isContinue = true;
static object locker = new object();
static void Main(string[] args)
{
test.ManagedAo(65);
Console.WriteLine("f2 = {0}", test.ManagedBo(10));
th = new Thread(new ThreadStart(Run));
th.Start();
while (isContinue)
{
Console.WriteLine("{0} - {1} - g_obuf[0] = {2} - g_obuf
[1] = {3}", test.MainFunctionCounter, test.RunMain,
test.OutputBuffer(0), test.OutputBuffer(1));
Thread.Sleep(1000);
}
}

static void Output()
{
Console.WriteLine("{0} - {1}", test.MainFunctionCounter,
test.RunMain);
}

static void Run()
{
test.RunMainFunc();
}
}
}
 
T

tat

Thanks, Peter. I did not write the old native C code so I can't say
that the global variables aren't marked "volatile". Anyway, here is a
code example
For native code which will be compiled into native DLL. Some usual
files that are generated by Visual Studio are omitted.
********** example for the native C code *************************
***defs.h****
#ifndef __DEFS_H__
#define __DEFS_H__

#define HR1_CH (0)
#define HR2_CH (1)
#define HR3_CH (2)
#define ARRAY_SIZE (5)
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void ao(unsigned char);
__declspec(dllexport) unsigned short bo(unsigned short);
__declspec(dllexport) unsigned short co[ARRAY_SIZE];
__declspec(dllexport) void mainFunction(void);
__declspec(dllexport) void initialize(void);

#ifdef __cplusplus
}
#endif
#endif
*****************************
***** globalData.h ********
*****************************
#ifndef __GLOBALDATA_H__
#define __GLOBALDATA_H__
#define BUF_SIZE 8
volatile long g_MainFunctionCounter;
volatile unsigned char g_ibuf[BUF_SIZE];
volatile unsigned char g_obuf[BUF_SIZE];
volatile int g_RunMain;
#endif // end of __GLOBALDATA_H__
**********************************
*********** ao.c ****************
**********************************
#include <stdio.h>
#include "defs.h"

void ao(unsigned char c)
{
printf("Input char = %c\n", c);
}
*******************************************
****************** bo.c *******************
*******************************************
#include <stdio.h>
#include "defs.h"

unsigned short bo(unsigned short c)
{
printf("Input number = %d\n", c);
return c;
}
*********************************************
**************** initialize.c ***************
*********************************************
#include "defs.h"
#include "globalData.h"

void initialize(void)
{
int i;
g_MainFunctionCounter = 0;
g_RunMain = 0;
for(i = 0; i < BUF_SIZE; i++)
{
g_ibuf = 0;
g_obuf = 0;
}
}
********************************************
********* mainFunction.c ***************
********************************************
#include <stdio.h>
#include "defs.h"
#include "globalData.h"

void mainFunction()
{
initialize();

while(g_RunMain == 1)
{
g_MainFunctionCounter++;
g_obuf[0]++;
g_obuf[1]--;
if (g_obuf[0] > 1000000)
{
g_obuf[0] = 0;
}
if(g_obuf[1] < -1000000)
{
g_obuf[1] = 0;
}
}

}
*******************************************
For managed wrapper
*********************************************
*********** ManagedLibraryDll.h *********
*********************************************
// ManagedLibraryDll.h

#pragma once

using namespace System;

namespace ManagedLibraryDll {

#include "../LibraryDll/defs.h"
#include "../LibraryDll/globalData.h"
public ref class ManagedFunctions
{
// TODO: Add your methods for this class here.
public:
ManagedFunctions();
~ManagedFunctions();
!ManagedFunctions();

property int RunMain
{
int get()
{
return g_RunMain;
}
}
property long MainFunctionCounter
{
long get()
{
return g_MainFunctionCounter;
}
}
void ManagedAo(unsigned char c);
unsigned short ManagedBo(unsigned short a);
void RunMainFunc(void);
void StopMainFunc(void);

unsigned char OutputBuffer(int idx);
unsigned char InputBuffer(int idx);

};
}
********************************************************
*********** ManagedLibraryDll.cpp *****************
********************************************************
// This is the main DLL file.

#include "stdafx.h"
#include "ManagedLibraryDll.h"
namespace ManagedLibraryDll
{
ManagedFunctions::ManagedFunctions()
{
}
ManagedFunctions::~ManagedFunctions() {}
ManagedFunctions::!ManagedFunctions() {}

void ManagedFunctions::ManagedAo(unsigned char c)
{
ao(c);
}

unsigned short ManagedFunctions::ManagedBo(unsigned short a)
{
return bo(a);
}

void ManagedFunctions::RunMainFunc()
{
g_RunMain = 1;
mainFunction();
}

void ManagedFunctions::StopMainFunc()
{
g_RunMain = 0;
}

unsigned char ManagedFunctions::OutputBuffer(int idx)
{
return g_obuf[idx];
}

unsigned char ManagedFunctions::InputBuffer(int idx)
{
return g_ibuf[idx];
}
}
Thanks,
TAT
***********************************************************************
C# application main program.cs
****
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using ManagedLibraryDll;

namespace TestCallManagedDllFromCsharp
{
class Program
{
static ManagedFunctions test = new ManagedFunctions();
static Thread th;
static bool isContinue = true;
static object locker = new object();
static void Main(string[] args)
{
test.ManagedAo(65);
Console.WriteLine("f2 = {0}", test.ManagedBo(10));
th = new Thread(new ThreadStart(Run));
th.Start();
while (isContinue)
{
Console.WriteLine("{0} - {1} - g_obuf[0] = {2} - g_obuf
[1] = {3}", test.MainFunctionCounter, test.RunMain,
test.OutputBuffer(0), test.OutputBuffer(1));
Thread.Sleep(1000);
}
}

static void Output()
{
Console.WriteLine("{0} - {1}", test.MainFunctionCounter,
test.RunMain);
}

static void Run()
{
test.RunMainFunc();
}
}
}
 
B

Ben Voigt [C++ MVP]

*****************************
***** globalData.h ********
*****************************
#ifndef __GLOBALDATA_H__
#define __GLOBALDATA_H__
#define BUF_SIZE 8
volatile long g_MainFunctionCounter;
volatile unsigned char g_ibuf[BUF_SIZE];
volatile unsigned char g_obuf[BUF_SIZE];
volatile int g_RunMain;
#endif // end of __GLOBALDATA_H__

You're defining variables in a header file. That's a bug, because now every
file that includes this header gets its own copy.

If you have any more questions about this ask again in the C++/CLI group
(microsoft.public.dotnet.languages.vc)
 
B

Ben Voigt [C++ MVP]

*****************************
***** globalData.h ********
*****************************
#ifndef __GLOBALDATA_H__
#define __GLOBALDATA_H__
#define BUF_SIZE 8
volatile long g_MainFunctionCounter;
volatile unsigned char g_ibuf[BUF_SIZE];
volatile unsigned char g_obuf[BUF_SIZE];
volatile int g_RunMain;
#endif // end of __GLOBALDATA_H__

You're defining variables in a header file. That's a bug, because now every
file that includes this header gets its own copy.

If you have any more questions about this ask again in the C++/CLI group
(microsoft.public.dotnet.languages.vc)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top