Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

1.Creating Threads Under Windows It is unfortunate that the C++ language didn\'t

ID: 664148 • Letter: 1

Question

1.Creating Threads Under Windows

It is unfortunate that the C++ language didn't standardize the method for creating threads. Therefore various compiler vendors invented their own solutions. If you are writing a program to run under Windows then you will want to use the WIN32 API to create your threads. The WIN32 API offers the following function to create a new thread:

uintptr_t _beginthread(

void( __cdecl *start_address )( void * ),

unsigned stack_size,

void *arglist

);

The use of the function is easier than it looks. The _beginthread() function takes 3 passed parameters.

The first is the name of the function which you want the new thread to begin executing. This is called the thread's entry-point-function. You need to create this function, and the only requirements are that it take a single passed parameter (of type void*) and that it returns nothing. That is what is meant by the function signature:

void( __cdecl *start_address )( void * ),

The second passed parameter is a requested stack size for the new thread; each thread gets its own stack. If you set this parameter to 0 the Windows operating system will select the stack size for me. If you don’t know what the stack size is, it is preferred to use 0.

The final passed parameter is the single parameter you want passed to the entry-point-function.

2.Use of Critical Section Objects

Critical section objects provide synchronization similar to that provided by mutex objects, except critical section objects can be used only by the threads of a single process. Event, mutex, and semaphore objects can also be used in a single-process application, but critical section objects provide a slightly faster, more efficient mechanism for mutual-exclusion synchronization. Like a mutex object, a critical section object can be owned by only one thread at a time, which makes it useful for protecting a shared resource from simultaneous access.

There is no guarantee about the order in which threads will obtain ownership of the critical section; however, the system will be fair to all threads.

The WIN32 API offers the following to create a critical section object:

Declare the critical section object cs as a global object.

CRITICAL_SECTION cs;

Initialize cs

InitializeCriticalSection( &cs );

Before a thread enters its critical section call the following

EnterCriticalSection( &cs );

After the thread finishes its critical section call the following

LeaveCriticalSection( &cs );

Run and Explain (25)

The best way to learn how to use WIN32 threads is to use it!

Please compile the sample program called mySample.cpp (also posted on the blackboard).

To run this sample program, simply request a WIN32 Console Application from Visual Studio's New Project Wizard. Then check Empty project check box in Application Settings dialog. After the creation of the project, you can add the source code mySample.cpp by selecting “Add Existing Item…” in Project menu. Please answer the following questions:

a.Run the program and report the result.

b.Try to comment out the call to the Sleep() function, compile, and run again, report the difference on the result.

c.Explain why the results are different.

3.Dining Philosopher problems (25)

The story of dining philosophers is described in section 5.7.3. With 5 philosophers sharing the chopsticks, there is always possibility that a deadlock may occur. The following three solutions solve the deadlock problem:

a.Allow at most four philosophers to be sitting simultaneously at the table.

b.Allow a philosopher to pick up her chopsticks only if both chopsticks are available.

c.Use asymmetric pick-up order. i.e. philosophers with odd numbers pick up her left chopsticks first and philosophers with even numbers pick up her right chopsticks first.

Explain that why the above three approaches are deadlock-free.

4.Programming - Dining Philosopher problem (50)

a.Implement a function called philosopher(), and write a program to create five threads of philosopher representing those five philosophers. The following is a framework for the function philosopher:

void philosopher( void *arg )

{

int left_stick, right_stick;

left_stick = (INT_PTR)arg;

right_stick = (INT_PTR)arg + 1;

if (right_stick >= 5) right_stick = 0;

/* ...... */

for (;;)

{

   printf("Philosopher [ %d ] is thinking. ",

              (INT_PTR)arg);

   Sleep(rand() % MAX_THINKING_TIME);

   if ((INT_PTR)arg % 2)

   {

        EnterCriticalSection(&mutex_stick[right_stick]);

        EnterCriticalSection(&mutex_stick[left_stick]);

   }

   else

   {

        EnterCriticalSection(&mutex_stick[left_stick]);

        EnterCriticalSection(&mutex_stick[right_stick]);

   }

// printf("Philosopher [%2d] is waiting. ",

//           (INT_PTR)arg);

   printf("Philosopher [%2d] is eating. ",

             (INT_PTR)arg);

   Sleep(rand() % MAX_EATING_TIME);

   /*......*/

   LeaveCriticalSection(&mutex_stick[left_stick]);

   LeaveCriticalSection(&mutex_stick[right_stick]);

} // for (;;)

}

Explanation / Answer

1.) #include<stdio.h>

#include<windows.h>

#include<process.h>

void silly(void *);

int main()

{

// this program first thread starts in main() function

printf("now in the main() function. ");

_beginthread(silly,0,(void*)12);

silly( (void*)-5);

sleep (100);

}

void silly(void *arg)

{

printf("The silly() function was passed %d ", (INT_PTR)arg );

}

4.) void philosopher(void *arg)

{

int left_stick, right_stick;

left_stick = (INT_PTR)arg;

right_stick = (INT_PTR)arg + 1;

if (right_stick >= 5) right_stick = 0;

for(i=1;i<=5;i++)

{

printf("philosopher [%d] is thinking. " , (INT_PTR)arg);

sleep(r and() %MAX_THINKING_TIME);

if ((INT_PTR)arg % 2)

{

EnterCriticalSection(&mutex_stick[right_stick]);

EnterCriticalSection(&mutex_stick[left_stick]);

}

else

{

EnterCriticalSection(&mutex_stick[left_stick]);

EnterCriticalSection(&mutex_stick[right_stick]);

}

printf("philosopher[%2d] is waiting. ", (INT_PTR)arg);

printf("philosopher [%2d] is eating. ", (INT_PTR)arg);

Sleep(r and() % MAX_EATING_TIME);

LeaveCriticalSection(&mutex_stick[left_stick]);

LeaveCriticalSection(&mutex_stick[right_stick]);

} for(i=1;i<5;i++)

}