Basic locking question in C# - c#

The classes:
public class SomeCollection
{
public void IteratorReset()
{
index = -1;
}
public bool IteratorNext()
{
index++;
return index < Count;
}
public int Count
{
get
{
return floatCollection.Count;
}
}
public float CurrentValue
{
get
{
return floatCollection[index];
}
}
public int CurrentIndex
{
get
{
return intCollection[index];
}
}
}
Class that holds reference to 'SomeCollection':
public class ThreadUnsafeClass
{
public SomeCollection CollectionObj
{
get
{
return collectionObj;
}
}
}
Classes ClassA, ClassB and ClassC contain the following loop that iterates over CollectionObj:
for (threadUnsafeClass.CollectionObj.IteratorReset(); threadUnsafeClass.CollectionObj.IteratorNext(); )
{
int currentIntIndex = threadUnsafeClass.CollectionObj.CurrentIndex;
float currentfloatValue = threadUnsafeClass.CollectionObj.CurrentValue;
// ...
}
Since I'm only reading CollectionObj in the 3 classes, I'm using multithreading for speedup, but I'm not quite sure how to enforce thread safety. I added a lock in ThreadUnsafeClass when retrieving CollectionObj, but the application throws an out of range exception.
Any help is appreciated.
Thank you !

You're only reading the CollectionObj property, but then you're mutating the object that the value refers to. See this bit:
for (threadUnsafeClass.CollectionObj.IteratorReset();
threadUnsafeClass.CollectionObj.IteratorNext(); )
Both IteratorReset and IteratorNext mutate SomeCollection by changing the value of index. Basically, you can't do this safely with your current code. Several threads could all call IteratorNext() at the same time, for example. The first call returns true, but before that thread gets a chance to read the values, the other threads make the index invalid.
Why are you using the collection itself for iteration? Typically you'd implement IEnumerable<T> and return a new object in GetEnumerator. That way different threads could each get a different object representing "their" cursor over the same collection. They could all iterate over it, and all see all the values.

The SomeCollection object is being referenced by each of the three classes A,B, and C, each of which is going to try and increment the internal index, causing the error(s). That said, you should be able to read objects in an array from multiple threads with something like the following:
public static object[] sharedList = new object[]{1,2,3,4,5};
public void Worker()
{
int localSum=0;
for(int i=0; i<sharedList.length; i++){
localSum += (int)sharedList[i];
}
}
The important thing here is that each thread will maintain it's own location within the array, unlike with the collectionObj.

Locking the CollectionObj property won't help. One possible problem is that all 3 threads are calling IteratorReset(), which sets the index to -1. Imagine the scenario where A starts the for loop, and gets to the first line in the loop before getting interrupted. Now B comes in and calls IteratorReset(), then gets interrupted to let A run again. Thread A executes the CurrentIndex property, which internally uses index = -1 due to B running. Boom, out of range exception.
There are other ways this can generate bad results, but that's probably the easiest to see. Is the intention to have all three threads go through each item on their own? Or are you expecting A, B, and C to divide up the work (like a consumer queue)?

Related

Which data structure allows adding from both sides, but enforces a capacity?

I require a data structure that has a capacity, but also that allows adding an item from either the front or the back. Each time an item is added, one item must be removed from the opposite end. My first thought was that this sound very similar to a Deque.
Is there an existing data structure that provides this functionality, or do I have to create it myself? If it does exist, does the .Net library have an implementation?
Thanks
I would suggest that you use a LinkedList, which gives you all the functionality you need. There are AddFirst and AddLast methods that let you add items at the front or back, and RemoveFirst and RemoveLast methods that let you remove from the front and back.
And, of course, there's a Count property that tells you how many items are in the list, so you can enforce your capacity requirement.
Not tested but something like this I think would work
public class Stack<T>
{
private T[] arr;
readonly int m_Size;
int m_StackPointer = 0;
public T this[int i]
{
get
{
if (i >= m_Size)
throw new IndexOutOfRangeException();
int pointer = i + m_StackPointer;
if (pointer >= (m_Size)) pointer -= m_Size;
return arr[pointer];
}
}
public void AddStart(T addItem)
{
m_StackPointer--;
if (m_StackPointer < 0) m_StackPointer = m_Size - 1;
arr[m_StackPointer] = addItem;
}
public void AddEnd(T addItem)
{
arr[m_StackPointer] = addItem;
m_StackPointer++;
if (m_StackPointer >= m_Size) m_StackPointer = 0;
}
public Stack()
: this(100)
{ }
public Stack(int size)
{
m_Size = size;
arr = new T[size];
}
}
I have decided that the best option is to use an array of T for the backing structure, and have a reference Front and a reference Back to represent the virtual start and end of the structure. I will also store a direction enum that will effectively indicate which direction the structure is facing(whether the last add operation was at the Front or the Back or a default if no add operations have been performed). This way, I can also implement an indexer with O(1) complexity, rather than iterating the collection.
Thanks for all of the responses. For some reason, I thought that I would need to move the data around in the backing structure. I didn't realize that this option is possible in C#.

Enumerating over lambdas does not bind the scope correctly?

consider the following C# program:
using System;
using System.Linq;
using System.Collections.Generic;
public class Test
{
static IEnumerable<Action> Get()
{
for (int i = 0; i < 2; i++)
{
int capture = i;
yield return () => Console.WriteLine(capture.ToString());
}
}
public static void Main(string[] args)
{
foreach (var a in Get()) a();
foreach (var a in Get().ToList()) a();
}
}
When executed under Mono compiler (e.g. Mono 2.10.2.0 - paste into here), it writes the following output:
0
1
1
1
This seems totally unlogical to me. When directly iterating the yield function, the scope of the for-loop is "correctly" (to my understanding) used. But when I store the result in a list first, the scope is always the last action?!
Can I assume that this is a bug in the Mono compiler, or did I hit a mysterious corner case of C#'s lambda and yield-stuff?
BTW: When using Visual Studio compiler (and either MS.NET or mono to execute), the result is the expected 0 1 0 1
I'll give you the reason why it was 0 1 1 1:
foreach (var a in Get()) a();
Here you go into Get and it starts iterating:
i = 0 => return Console.WriteLine(i);
The yield returns with the function and executes the function, printing 0 to the screen, then returns to the Get() method and continues.
i = 1 => return Console.WriteLine(i);
The yield returns with the function and executes the function, printing 1 to the screen, then returns to the Get() method and continues (only to find that it has to stop).
But now, you're not iterating over each item when it happens, you're building a list and then iterating over that list.
foreach (var a in Get().ToList()) a();
What you are doing isn't like above, Get().ToList() returns a List or Array (not sure wich one). So now this happens:
i = 0 => return Console.WriteLine(i);
And in you Main() function, you get the following in memory:
var i = 0;
var list = new List
{
Console.WriteLine(i)
}
You go back into the Get() function:
i = 1 => return Console.WriteLine(i);
Which returns to your Main()
var i = 1;
var list = new List
{
Console.WriteLine(i),
Console.WriteLine(i)
}
And then does
foreach (var a in list) a();
Which will print out 1 1
It seems like it was ignoring that you made sure you encapsulated the value before returning the function.
#Armaron - The .ToList() extension returns List of type T as ToArray() returns T[] as the naming convention implies, but I think you are on the right track with your response.
This sounds like an issuse with the compiler. I agree with Servy that it is probably a bug, however, have you tried the following?
public class Test
{
private static int capture = 0;
static IEnumerable<Action> Get()
{
for (int i = 0; i < 2; i++)
{
capture++;
yield return () => Console.WriteLine(capture.ToString());
}
}
}
Additionally you may want to try the static approach, perhaps this will perform a more accurate conversion as your function is static.
List<T> list = Enumerable.ToList(Get());
When calling ToList() it seems as though it is not performing a single iteration for each value but rather:
return new List<T>(Get());
The second for each in your code does not make sense to me in implementation as to why it would ever be necessary or beneficial unless you require additional actions to be added/removed to the List object. The first makes perfect sense since all you are doing is iterating through the object and performing the associated action. My understanding is that an integer within the scope of the static IEnumerbale object is being calculated during conversion by performing the entire iteration and the action is preserving the int as a static int due to scope. Also, keep in mind that IEnumerable is merely an interface that is implemented by List which implements IList, and may contain logic for the conversion built in.
That being said I am interested to see/hear your findings as this is an interesting post. I will definitely upvote the question. Please ask questions if anything I said needs clarification or if something is false say so, although I am confident in my usage of the yield keyword of IEnumerable but this is a unique issue.

Find next incremental value not in existing list using linq

I have two methods in an IntExtensions class to help generate the next available incremental value (which is not in a list of existing integers which need to be excluded).
I dont think I'm addressing the NextIncrementalValueNotInList method in the best way and am wondering if I can better use linq to return the next available int?
public static bool IsInList(this int value, List<int> ListOfIntegers) {
if (ListOfIntegers.Contains(value))
return true;
return false;
}
public static int NextIncrementalValueNotInList(this int value,
List<int> ListOfIntegers) {
int maxResult;
maxResult = ListOfIntegers.Max() + 1;
for (int i = value; i <= maxResult; i++)
{
if (!(i.IsInList(ListOfIntegers)))
{
return i;
}
}
return maxResult;
}
Using linq your method will look like:
return IEnumerable.Range(1, ListOfIntegers.Count + 1)
.Except(ListOfIntegers)
.First();
I guess it starting at 1.
You could also proceed like this:
IEnumerable.Range(1, ListOfIntegers.Count)
.Where(i => !ListOfIntegers.Contains(i))
.Union(new []{ ListOfIntegers.Count + 1 })
.First();
You don't actually need to calculate the Max value - just keep incrementing i until you find a value that doesn't exist in the list, e.g:
public static int NextIncrementalValueNotInList(this int value,
List<int> ListOfIntegers)
{
int i = value;
while(true)
{
if (!(i.IsInList(ListOfIntegers)))
{
return i;
}
i++;
}
return maxResult;
}
. Besides that, I'm not sure if there's much more you can do about this unless:
ListOfIntegers is guaranteed to be, or needs to be, sorted, or
ListOfIntegers doesn't actually need to be a List<int>
If the answer to the first is no, and to the second is yes, then you might instead use a HashSet<int>, which might provide a faster implementation by allowing you to simply use HashSet<T>'s own bool Contains(T) method:
public static int NextIncrementalValueNotInList(this int value,
HashSet<int> ListOfIntegers)
{
int i = value;
while(true)
{
if (!(ListOfIntegers.Contains(i))
{
return value;
}
i++;
}
}
Note that this version shows how to do away with the Max check also.
Although be careful of premature optimisation - if your current implementation is fast enough, then I wouldn't worry. You should properly benchmark any alternative solution with extreme cases as well as real-world cases to see if there's actually any difference.
Also what you don't want to do is use my suggestion above by turning your list into a HashSet for every call. I'm suggesting changing entirely your use of List to HashSet - any piecemeal conversion per-call will negate any potential performance benefits due to the overhead of creating the HashSet.
Finally, if you're not actually expecting much fragmentation in your integer list, then it's possible that a HashSet might not be much different from the current Linq version, because it's possibly going to end up doing similar amounts of work anyway.

Run multiply instances of the same method simultaneously in c# without data loss?

I really don't understand Tasks and Threads well.
I have a method inside three levels of nested for that I want to run multiple times in different threads/tasks, but the variables I pass to the method go crazy, let me explain with some code:
List<int> numbers=new List<int>();
for(int a=0;a<=70;a++)
{
for(int b=0;b<=6;b++)
{
for(int c=0;b<=10;c++)
{
Task.Factory.StartNew(()=>MyMethod(numbers,a,b,c));
}
}
}
private static bool MyMethod(List<int> nums,int a,int b,int c)
{
//Really a lot of stuff here
}
This is the nest, myMethod really does a lot of things, like calculating the factorial of some numbers, writing into different documents and matching responses with a list of combinations and calling other little methods, it has also some return value (booleans), but I don't care about them at the moment.
The problem is that no task reach an end, it's like everytime the nest call the method it refreshes itself, removing previous instances.
It also give an error, "try to divide for 0", with values OVER the ones delimited by FORs, for example a=71, b=7, c=11 and all variables empty(that's why divided by zero). I really don't know how to solve it.
The problem is, that you are using a variable that has been or will be modifed outside your closure/lambda. You should get a warning, saying "Access to modified closure".
You can fix it by putting your loop variables into locals first and use those:
namespace ConsoleApplication9
{
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var numbers = new List<int>();
for(int a=0;a<=70;a++)
{
for(int b=0;b<=6;b++)
{
for(int c=0;c<=10;c++)
{
var unmodifiedA = a;
var unmodifiedB = b;
var unmodifiedC = c;
Task.Factory.StartNew(() => MyMethod(numbers, unmodifiedA, unmodifiedB, unmodifiedC));
}
}
}
}
private static void MyMethod(List<int> nums, int a, int b, int c)
{
//Really a lot of stuffs here
}
}
}
Check your for statements. b and c are never incremented.
You then have a closure over the loop variables which is likely to be the cause of other problems.
Captured variable in a loop in C#
Why is it bad to use an iteration variable in a lambda expression

Can I retrieve the stored value x in a hashset given an object y where x.Equals(y)

[TestFixture]
class HashSetExample
{
[Test]
public void eg()
{
var comparer = new OddEvenBag();
var hs = new HashSet<int>(comparer);
hs.Add(1);
Assert.IsTrue(hs.Contains(3));
Assert.IsFalse(hs.Contains(0));
// THIS LINE HERE
var containedValue = hs.First(x => comparer.Equals(x, 3)); // i want something faster than this
Assert.AreEqual(1, containedValue);
}
public class OddEvenBag : IEqualityComparer<int>
{
public bool Equals(int x, int y)
{
return x % 2 == y % 2;
}
public int GetHashCode(int obj)
{
return obj % 2;
}
}
}
As well as checking if hs contains an odd number, I want to know what odd number if contains. Obviously I want a method that scales reasonably and does not simply iterate-and-search over the entire collection.
Another way to rephrase the question is, I want to replace the line below THIS LINE HERE with something efficient (say O(1), instead of O(n)).
Towards what end? I'm trying to intern a laaaaaaaarge number of immutable reference objects similar in size to a Point3D. Seems like using a HashSet<Foo> instead of a Dictionary<Foo,Foo> saves about 10% in memory. No, obviously this isn't a game changer but I figured it would not hurt to try it for a quick win. Apologies if this has offended anybody.
Edit: Link to similar/identical post provided by Balazs Tihanyi in comments, put here for emphasis.
The simple answer is no, you can't.
If you want to retrieve the object you will need to use a HashSet. There just isn't any suitable method in the API to do what you are asking for otherwise.
One optimization you could make though if you must use a Set for this is to first do a contains check and then only iterate over the Set if the contains returns true. Still you would almost certainly find that the extra overhead for a HashMap is tiny (since essentially it's just another object reference).

Categories