Array of Monitors in C# - c#

I'm currently trying to implement the Dining Philosopher problem, however I'm running into an issue. I declare my forks as such
public static fixed Monitor forks[5];
however when I try to reference them via
forks[i].Enter();
I'm only given the possibility of "Equals, GetType, ToString, GetHashCode."
Does anyone know how to create an array of Monitors and lock each specific Monitor?

You just need to create an array of objects - you can't create an instance of Monitor; it's a static class. (I'm surprised you can even declare the array - although it's not clear why you've decided to use fixed sized buffers, either. Stick with safe code, I suggest.)
So:
object[] forks = new object[5];
for (int i = 0; i < forks.Length; i++)
{
forks[i] = new object();
}
Then you can use:
Monitor.Enter(forks[x]);
to acquire the monitor for the index x.

In C#, you can lock on any object, methods on Monitor are static.
So your code should be done this way:
List<object> locks = new List<object>();
for (int i = 0; i < 5; i++) locks.Add(new object());
// ...
Monitor.Enter(locks[0]);

Related

Difference between copying reference of a class and copying value

For an experiment, I tried this :
(1) Create 100000 classes, each of them wrapping a double variable
---This is the experiment part---
(2) Measured performance of two methods by running 100000 times :
create a double[] and assign the value of wrapped variables.
create a class[] and assign the reference of wrapping class.
The above may confuse you, so I am attaching the code :
static void Main(string[] args)
{
int length = 100000;
Test test = new Test(length);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < length; i++)
test.CopyValue();
//test.CopyReference(); //test.CopyValue(); or test.CopyReference();
stopwatch.Stop();
Console.WriteLine("RunTime : {0} ", stopwatch.ElapsedMilliseconds);
}
class DoubleWrapper
{
public double value = 0.0;
}
class Test
{
DoubleWrapper[] wrapper;
public void CopyValue()
{
double[] x = new double[wrapper.Length];
for (int i = 0; i < wrapper.Length; i++)
x[i] = wrapper[i].value;
}
public void CopyReference()
{
DoubleWrapper[] x = new DoubleWrapper[wrapper.Length];
for (int i = 0; i < wrapper.Length; i++)
x[i] = wrapper[i];
}
public Test(int length)
{
wrapper = new DoubleWrapper[length];
for (int i = 0; i < length; i++)
wrapper[i] = new DoubleWrapper();
}
}
The result is as follows :
test.CopyValue() : 56890 (millisec)
test.CopyReference() : 66688 (millisec)
(built with release configuration and ran exe)
I tried several times, but the result doesn't change much.
So I concluded that CopyReference() takes longer time.
But I hardly understand why. Here is the question :
I thought that, regardless of CopyValue() or CopyReference(), what my machine does is "Copying a number in memory" though one is double value and the another is reference to a class. So there should not be meaningful difference in performance, but the fact is not.
Then what is the difference between copying a value and copying a reference?
Does copying a reference do more thing than copying a value?
(When passing a reference without ref keyword, isn't it true that reference is copied as if it were value? What I am saying is that,
ClassA x = new ClassA();
ClassA y = x;
means making a copy of "reference of x" and then assigning to variable y, consequently y = null doesn't affect x at all. Is this true?)
If I am working with wrong assumptions, please let me know what I am wrong with.
I appreciate your help and advice.
-
I guessed that GC might have some impact, but turning off GC by TryStartNoGCRegion(Int64) doesn't change the conclusion.
(both become faster, but still CopyReference() is slower.)
means making a copy of "reference of x" and then assigning to variable
y, consequently y = null doesn't affect x at all. Is this true?
That's correct - you made a copy of reference.
Now, what about why your implementation of CopyReference is slower.
You have to do performance analysis to get real insight about it, but on top of my head:
You're creating a new instance of DoubleWrapper reference type, inside that method.
Remember, that C# is not "zero-cost abstraction" language, like C/C++/Rust might be.
Creating an instance of, even simple reference type, that does nothing more than a simple wrapper over a primitive type, suppose to cost you more. Because that instance has more in it than a simple double value - the size of DoubleWrapperobject will not be equal to 8 bytes.
Reading about the stack and the heap may help you understand. if you copy a reference, you essentially copy the pointer showing to the actual object in the heap, and if that actual object changes, those changes are shown on every thing that references that object.
If you do a "deep copy", or a clone (like when implementing IClonable) you will duplicate that data in the stack and create a pointer to it, thus not beeing dependant on the original object any longer.
I hope this explanation helps you a little bit? See this for some information https://www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-i/ on the stack and heap.

what is a Double Pointer equivalent in c#?

I'm trying to convert a c++ code into c# and I encountered a double pointer. I'm wondering how can double pointers be implemented in c#?
if I have say,
MyClass **MyClasses;
and it was initialized like this.
MyClasses = new MyClass*[ClassNums];
in another function inside the class, every subitems were initialized in a loop.
for(num = 0; num < classnum; num++)
{
MyClasses[subnum] = new MyClass();
}
and this double-pointer is being used like this.
MyClasses[subnum]->MyMethod();
How can this be converted into c#? I tried to use an array of MyClasses[] but i'm not quite sure about it. Also, I cannot test this because it's from a static library and the components which are using it are not yet converted into c#. Should I use generic lists or something?
In this case, the outer pointer is being used to illustrate a spannable range, as shown in the loop here:
for(num = 0; num < classnum; num++)
{
MyClasses[subnum] = new MyClass();
}
So the outer pointer should probably be replaced by a list, array or IEnumerable<T> sequence.
The inner pointer is being used to direct to an object, so that should be replaced with a reference.
So: unless there is something very specific that the C++ code is doing, all you need here is:
MyClass[] arr = ...
...
for(int i = 0, i < arr.Length ; i++)
{
arr[i] = new MyClass();
}
...
arr[i].MyMethod();
Note that this can only be interpreted by looking at the code. There are other possible ways to talk about "double pointers*; consider this ref example:
void SomeMethod(ref MyClass obj) {...}
Here obj is a reference to a reference (to a MyClass)–with everything being double-dereferenced automatically (or a single-dereferencing assignment if you change the value of obj). This too would be comparable to a double-pointer.

Halt until object created successfully [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm a beginner programmer and need some help. In the beginning of my program, 5 bunnies (object type Bunny) are created. It looks like this:
List<Bunny> bunnies = new List<Bunny>();
Bunny newBunny;
for(int i = 0; i < 5; i++)
{
newBunny = new Bunny();
bunnies.Add(newBunny);
}
My problem is that the construction of newBunny takes too long and the program continues with the for-loop. This causes the list to have just the first constructed newBunny and duplicates of it.Running the code prints me the following:
Name-Kate, Gender-Male, Color-White, Age-0, Radioactive-False
Name-Kate, Gender-Male, Color-White, Age-0, Radioactive-False
Name-Kate, Gender-Male, Color-White, Age-0, Radioactive-False
Name-Kate, Gender-Male, Color-White, Age-0, Radioactive-False
Name-Kate, Gender-Male, Color-White, Age-0, Radioactive-False
The construction looks like this:
public Bunny()
{
Random randNum = new Random ();
int namesCount = Enum.GetNames(typeof(BunnyName)).Length;
Name=((BunnyName)(randNum. Next(0, namesCount)));
int genderCount = Enum.GetNames(typeof(BunnyGender)).Length;
Gender=((BunnyGender)(randNum. Next(0, genderCount)));
int colorCount = Enum.GetNames(typeof(BunnyColor)).Length;
Color=((BunnyColor)(randNum. Next(0, colorCount)));
Age=-1;
if(randNum. Next(1,101)<2)
Radioactive = true;
else
Radioactive =false;
}
I want the program to halt until the construction of newBunny ends, and only then to add it to the list:
List<Bunny> bunnies = new List<Bunny>();
Bunny newBunny;
for(int i = 0; i < 5; i++)
{
//stop until next line finishes
newBunny = new Bunny();
//continue
bunnies.Add(newBunny);
}
Ps. If I'm debugging the program it runs just fine, exactly like i want it to (new bunnies not 'duplicates')
Also, if I add a messageBox in the end of the for-loop, everything works good.
This is why i thought it might need a halt
for(int i = 0; i < 5; i++)
{
//stop until next line finishes
newBunny = new Bunny();
//continue
bunnies.Add(newBunny);
MessageBox.Show("test");
}
Hope you understood my problem, thanks.
Random in a loop? They may be different objects but all your random numbers are the same.
This is because the constructor for Random, when given no parameters uses a seed from the system clock. So if you new them up quickly like this they all end up the same and will give the same value when you call Next.
Much better to pass one Random into all of the constructors and use that instead.
List<Bunny> bunnies = new List<Bunny>();
Random random = new Random();
for(int i = 0; i < 5; i++)
{
bunnies.Add(new Bunny(random));
}
You also don't need a variable to hold the bunnies at an unnecessarily high scope. If your using something in the for loop only, it doesn't need to exist outside of it.
Having a static Random in the Bunny class has been suggested, but i'd advise against it. There are a lot of benefits of injecting things into the instance (especially when mult-threading), but in your case the advantage is testability.
I've included a class below as an example of something you could use to test your Bunny constructor, you can control the bunny that gets made and then verify that what happened is correct:
class MyRandomIsAlwaysN : Random
{
private readonly int nextValue;
public MyRandomIsAlwaysN(int n){
this.nextValue = n;
}
public override int Next(int x, int y){
return this.nextValue
}
}
The problem you have is in your usage of Random.
See here: C# Random Numbers aren't being "random"
I would suggest you create one Random class outside of bunny, and then pass that into the constructor.
i.e
List<Bunny> bunnies = new List<Bunny>();
Bunny newBunny;
Random randomGenerator = new Random();
for(int i = 0; i < 5; i++)
{
newBunny = new Bunny(randomGenerator);
bunnies.Add(newBunny);
}
Your program execution is totally synchronous so in fact there are 5 different instances of Bunny in the list.
If you don't believe me change the constructor of Bunny and add an integer to it. In the constructor assign this integer to an instance variable of Bunny like so:
public class Bunny{
private int _instanceId;
public Bunny(int instanceId){
_instanceId = instanceId;
}
}
in the loop do this :
newBunny = new Bunny(i);
now use the debugger to step through the code. Hopefully visual studio. Put a break point on the add statement and navigate/hover the cursor over the bunnies variable to see what is inside. You can even inspect the different instances and you will see the instanceid is different.
Your code just creates 5 different instances of Bunny, but because the constructor is the same, you end up with 5 instances that look exactly the same.
To get really random values do this in your constructor :
static Random randNum = new Random ();

Array through parameter by reference affecting another array

CardDetails is a Structure.
public static void ParceIntricaciesJabber(ref CardDetails[] WhichArray)
{
WhichArray[0].ID = 50;
WhichArray[0].Type = "None";
}
In calling:
ParceIntricaciesJabber(ref OpponentCards);
After I call the function though, another Array called PlayerCards is affected in the exact same way as OpponentCards - despite being declared as two different arrays. They have the same number of elements and the same data Type, and that's it.
This probably should be obvious but i'm not seeing it. The code works in VB.NET. What am I doing wrong?
EDIT: Initialization Code:
public static class Module1{
public static CardDetails[] PlayerCards = new CardDetails[100];
public static CardDetails[] OpponentCards = new CardDetails[100];
}
And also when navigating to the Form
for (int n = 1; n <= 100; n++)
{
Module1.PlayerCards[n] = new CardDetails();
Module1.OpponentCards[n] = new CardDetails();
}
My guess is that you are sharing the reference to the arrays. Even though it is structs inside the array, the array itself is a reference type. You will need to post your array instantiation code to verify one way or the other though

Is this a good practice of immutability?

Good morning,
Suppose I have a class
public class Class
{
int something;
int[] otherThing;
}
and I want to make objects of type Class immutable. Suppose also that I have a very frequent operation which creates a new object of type Class,
public Class SomeFunction()
{
int[] Temp = new int[] { ... };
return new Class(1, Temp);
}
To avoid creating new objects too often, and since Tempis no longer accessible out of the method, is it too bad to set on the constructor
this.otherThing = Temp;
instead of
otherThing = new uint[Temp.Length];
for (int i = 0; i < Temp.Length; i++)
{
this.otherThing[i] = Temp[i];
}
?
Thank you very much.
If the constructor that does this is private its fine IMO. Since you know the content of the other array will never change you can directly use it. You could even share one instance of the array between several instances of your class if you want to without causing any problems.
A public constructor directly using a provided array is a bad idea on the other hand. Since that can be used to break immutability.
It is better to assign a copy of temp to otherThing so that any changes to otherThing will not change temp. You can also use the Array.CopyTo method for this purpose.
In addition you should seriously consider using IEnumerable<int> or IList<int> instead of int[] because arrays by nature work against the idea of immutability. Read this blog post by Eric Lippert.
The difference is that in the first option you always get a new instance and in the second one all the created "Class"es will point to the same array (!). So if you change something in the array in any Class, all the other classes are changed.

Categories