-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #432 from mpostol/Monitor
Monitor => master - working on concurrent programming.
Showing
8 changed files
with
284 additions
and
10 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
ConcurrentProgramming/CommonDataConsistency/CommonDataConsistency.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
ConcurrentProgramming/CommonDataConsistency/CriticalSectionLock.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
//____________________________________________________________________________________________________________________________________ | ||
// | ||
// Copyright (C) 2024, Mariusz Postol LODZ POLAND. | ||
// | ||
// To be in touch join the community by pressing the `Watch` button and get started commenting using the discussion panel at | ||
// | ||
// https://github.com/mpostol/TP/discussions/182 | ||
// | ||
//_____________________________________________________________________________________________________________________________________ | ||
|
||
namespace TP.ConcurrentProgramming.CommonDataConsistency | ||
{ | ||
/// <summary> | ||
/// Code sample to examine data consistence in th concurrent programming environment | ||
/// </summary> | ||
public class CriticalSectionLock | ||
{ | ||
#region Monitor methods | ||
|
||
private readonly Lock _lockObj = new(); | ||
|
||
public void NoProtectedMethod(object? state) | ||
{ | ||
CommonDataProcessingSimulator(); | ||
} | ||
|
||
public void ProtectedMethod(object? state) | ||
{ | ||
using (_lockObj.EnterScope()) | ||
{ | ||
CommonDataProcessingSimulator(); | ||
} | ||
} | ||
|
||
#endregion Monitor methods | ||
|
||
#region private | ||
|
||
private int m_IntegerA = 0; | ||
private int m_IntegerB = 0; | ||
private Random m_Random = new Random(); | ||
|
||
private void CommonDataProcessingSimulator() | ||
{ | ||
for (int i = 0; i < 1000000; i++) | ||
{ | ||
int _value = m_Random.Next(0, 10000); | ||
m_IntegerA = _value; | ||
m_IntegerB = -_value; | ||
IsConsistent &= m_IntegerA + m_IntegerB == 0; | ||
} | ||
} | ||
|
||
#endregion private | ||
|
||
#region UT Instrumentation | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether this instance is consistent. | ||
/// </summary> | ||
/// <remarks>Always must be true.</remarks> | ||
/// <value><c>true</c> if this instance is consistent; otherwise, <c>false</c>.</value> | ||
public bool IsConsistent = true; | ||
|
||
#endregion UT Instrumentation | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
ConcurrentProgramming/CommonDataConsistencyUnitTest/CommonDataConsistencyUnitTest.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
ConcurrentProgramming/CommonDataConsistencyUnitTest/CriticalSectionLockUnitTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
//____________________________________________________________________________________________________________________________________ | ||
// | ||
// Copyright (C) 2024, Mariusz Postol LODZ POLAND. | ||
// | ||
// To be in touch join the community by pressing the `Watch` button and get started commenting using the discussion panel at | ||
// | ||
// https://github.com/mpostol/TP/discussions/182 | ||
// | ||
//_____________________________________________________________________________________________________________________________________ | ||
|
||
namespace TP.ConcurrentProgramming.CommonDataConsistency.UnitTest | ||
{ | ||
[TestClass] | ||
public class CriticalSectionLockUnitTest | ||
{ | ||
/// <summary> | ||
/// Test lack of data consistency using manually created <seealso cref="Thread"/>. | ||
/// </summary> | ||
[TestMethod] | ||
public void LackOfDataConsistencyUsingManuallyCreatedThreads() | ||
{ | ||
CriticalSectionLock m_ThreadsExample = new CriticalSectionLock(); | ||
RunConcurrentlyManualyCreatedThreads(m_ThreadsExample.NoProtectedMethod); | ||
Assert.IsFalse(m_ThreadsExample.IsConsistent); | ||
} | ||
|
||
/// <summary> | ||
/// Test how to protect data consistency using critical section implemented using Monitor and manually created <seealso cref="Thread"/>. | ||
/// </summary> | ||
[TestMethod] | ||
public void CriticalSectionImplementedUsingMonitorManuallyCreatedThreads() | ||
{ | ||
CriticalSectionLock m_ThreadsExample = new CriticalSectionLock(); | ||
RunConcurrentlyManualyCreatedThreads(m_ThreadsExample.ProtectedMethod); | ||
Assert.IsTrue(m_ThreadsExample.IsConsistent); | ||
} | ||
|
||
/// <summary> | ||
/// Test lack of data consistency using <seealso cref="ThreadPool"/>. | ||
/// </summary> | ||
[TestMethod] | ||
public void LackOfDataConsistencyUsingThreadPool() | ||
{ | ||
CriticalSectionLock m_ThreadsExample = new CriticalSectionLock(); | ||
RunThreadsUsingThreadPool(m_ThreadsExample.NoProtectedMethod); | ||
Assert.IsFalse(m_ThreadsExample.IsConsistent); | ||
} | ||
|
||
/// <summary> | ||
/// Test how to protect data consistency using critical section implemented using Monitor and <seealso cref="ThreadPool"/>. | ||
/// </summary> | ||
[TestMethod] | ||
public void CriticalSectionImplementedUsingMonitorThreadPool() | ||
{ | ||
CriticalSectionLock m_ThreadsExample = new CriticalSectionLock(); | ||
RunThreadsUsingThreadPool(m_ThreadsExample.ProtectedMethod); | ||
Assert.IsTrue(m_ThreadsExample.IsConsistent); | ||
} | ||
|
||
/// <summary> | ||
/// Test lack of data consistency using manually created <seealso cref="Task"/> | ||
/// </summary> | ||
[TestMethod] | ||
public void CheckConsitencyUsingTaskNoMonitor() | ||
{ | ||
CriticalSectionLock m_ThreadsExample = new CriticalSectionLock(); | ||
RunThreadsUsingTask(m_ThreadsExample.NoProtectedMethod); | ||
Assert.IsFalse(m_ThreadsExample.IsConsistent); | ||
} | ||
|
||
/// <summary> | ||
/// Test how to protect data consistency using critical section implemented using Monitor and <seealso cref="Task"/>. | ||
/// </summary> | ||
[TestMethod] | ||
public void CheckWhetherThreadsUsingThreadPoolAreSynchronized() | ||
{ | ||
CriticalSectionLock m_ThreadsExample = new CriticalSectionLock(); | ||
RunThreadsUsingTask(m_ThreadsExample.ProtectedMethod); | ||
Assert.IsTrue(m_ThreadsExample.IsConsistent); | ||
} | ||
|
||
#region Test Instrumentation | ||
|
||
public void RunConcurrentlyManualyCreatedThreads(ParameterizedThreadStart start) | ||
{ | ||
if (start == null) | ||
throw new ArgumentNullException(nameof(start)); | ||
Thread[] threadsArray = new Thread[2]; | ||
for (int i = 0; i < threadsArray.Length; i++) | ||
threadsArray[i] = new Thread(start); | ||
foreach (Thread _thread in threadsArray) | ||
_thread.Start(); | ||
foreach (Thread _thread in threadsArray) | ||
_thread.Join(); | ||
} | ||
|
||
public void RunThreadsUsingThreadPool(WaitCallback callBack) | ||
{ | ||
for (int i = 0; i < 2; i++) | ||
ThreadPool.QueueUserWorkItem(callBack); | ||
//wait for threads | ||
//TODO must be improved it could cause race condition | ||
Thread.Sleep(1000); | ||
} | ||
|
||
public void RunThreadsUsingTask(WaitCallback callBack) | ||
{ | ||
if (callBack == null) | ||
throw new ArgumentNullException(nameof(callBack)); | ||
List<Task> _tasksInProgress = new List<Task>(); | ||
for (int i = 0; i < 2; i++) | ||
_tasksInProgress.Add(Task.Run(() => callBack(null))); | ||
//wait for threads | ||
Task.WaitAll(_tasksInProgress.ToArray()); | ||
} | ||
|
||
#endregion Test Instrumentation | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
//____________________________________________________________________________________________________________________________________ | ||
// | ||
// Copyright (C) 2024, Mariusz Postol LODZ POLAND. | ||
// | ||
// To be in touch join the community by pressing the `Watch` button and get started commenting using the discussion panel at | ||
// | ||
// https://github.com/mpostol/TP/discussions/182 | ||
// | ||
//_____________________________________________________________________________________________________________________________________ | ||
|
||
namespace TP.ConcurrentProgramming.Fundamentals | ||
{ | ||
public abstract class HoareMonitor | ||
{ | ||
protected interface ISignal | ||
{ | ||
/// <summary> | ||
/// A thread that changes the state of the monitor in a way that might allow a waiting thread to proceed will signal the <see cref="ISignal"/> variable and, | ||
/// as a result, awake up one of the waiting threads. | ||
/// </summary> | ||
/// <remarks> | ||
/// The send signal operation needs some scheduling decisions. After sending a signal the thread should immediately wake up the waiting one, if any, | ||
/// and give up the monitor to it. It means that the monitor is transferred from a thread issuing a signal to the signaled one. | ||
/// The suspended process will afterward regain the processor. This kind of scheduling treats the waiting process as a continuation of the thread that has established | ||
/// the awaited condition. The main advantage of the above solution could be revealed when the program validity is proved because the monitor is not released at all, | ||
/// and thereby there is no possibility to change the data enclosed by the monitor, and the established condition as well, by another, third process. | ||
/// </remarks> | ||
void Send(); | ||
|
||
/// <summary> | ||
/// A thread that cannot proceed because an event is not met will wait on a signal variable. | ||
/// </summary> | ||
/// <remarks> | ||
/// After invoking the wait operation the current process releases all the monitors that it possesses, thus it must leave all relevant data in a consistent state. | ||
/// There must be initiated a scheduling mechanism to choose another process to run because the processor is released as well. | ||
/// </remarks> | ||
void Wait(); | ||
|
||
/// <summary> | ||
/// Check if any thread is waiting for the specified signal | ||
/// </summary> | ||
bool Await(); | ||
} | ||
|
||
protected interface ICondition | ||
{ | ||
/// <summary> | ||
/// A thread that changes the state of the monitor in a way that might allow a waiting thread to proceed will signal the condition variable and, | ||
/// as a result, awake up one of the waiting threads. | ||
/// </summary> | ||
/// <remarks> | ||
/// This operation is based upon the principle that the signaling thread keeps control of the monitor, and the signaled one changes only its state and becomes ready to run. | ||
/// Of course, it cannot be assumed that the announced condition is still fulfilled when the signaled process is resumed, because other processes, | ||
/// taking precedence, may have changed it in the meantime. Therefore, the signaled process, just after taking the control, should check again the condition, | ||
/// except that it cannot be changed, and, if necessary, wait once more for its occurrence. | ||
/// </remarks> | ||
void Send(); | ||
|
||
/// <summary> | ||
/// A thread that cannot proceed because an event is not met will wait on a condition variable. | ||
/// </summary> | ||
/// <remarks> | ||
/// After invoking the wait operation the current process releases all the monitors that it possesses, thus it must leave all relevant data in a consistent state. | ||
/// There must be initiated a scheduling mechanism to choose another process to run because the processor is released as well. | ||
/// </remarks> | ||
void Wait(); | ||
|
||
/// <summary> | ||
/// Check if any thread is waiting for the specified signal | ||
/// </summary> | ||
bool Await(); | ||
} | ||
|
||
/// <summary> | ||
/// Creates <see cref="ISignal"/> to be instantiated and used inside the monitor. If <see cref="ISignal"/> is not used in the context of the monitor it was created an exception is thrown. | ||
/// </summary> | ||
/// <returns>a new instance of <see cref="ISignal"/> attached to this monitor.</returns> | ||
protected abstract ISignal CreateSignal(); | ||
|
||
/// <summary> | ||
/// Creates <see cref="ICondition"/> to be instantiated and used inside the monitor. If <see cref="ISignal"/> is not used in the context of the monitor it was created an exception is thrown. | ||
/// </summary> | ||
/// <returns></returns> | ||
protected abstract ICondition GetCondition(); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...ntProgramming/ReactiveInteractiveUserInterface/BusinessLogicTest/BusinessLogicTest.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters