-3
unordered_map<std::string,unordered_map<std::string, std::string> >* storing_vars;

I have this variable in the scope declared in the scope.

This is declared in the constructor.

this->storing_vars =  new unordered_map<std::string,unordered_map<std::string, std::string> >();

in order to initialize it.

Then what I do is call a function over and over again by my BackgroundWorker

for(int i2 = 0; i2 < 30; i2++){



                int index_pos_curr = i2;


                //Start the Threads HERE


                this->backgroundWorker2 = gcnew System::ComponentModel::BackgroundWorker;
                this->backgroundWorker2->WorkerReportsProgress = true;
                this->backgroundWorker2->WorkerSupportsCancellation = true;


                //this->backgroundWorker2->FieldSetter(L"std::string",L"test","damnnit");

                backgroundWorker2->DoWork += gcnew DoWorkEventHandler( this, &MainFacebook::backgroundWorker2_DoWork );
                backgroundWorker2->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &MainFacebook::backgroundWorker2_RunWorkerCompleted );
                backgroundWorker2->ProgressChanged += gcnew ProgressChangedEventHandler( this, &MainFacebook::backgroundWorker2_ProgressChanged );
                backgroundWorker2->RunWorkerAsync(index_pos_curr);
                Sleep(50); //THE PROBLEM IS HERE, IF I COMMENT THIS OUT it won't work, that's probably because there are a lot of functions trying to add values in the same variable (even though the indexes are differents in each call)
            }

After this is done it calls the DoWork Function

void backgroundWorker2_DoWork(Object^ sender, DoWorkEventArgs^ e ){
             BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);         
             e->Result = SendThem( safe_cast<Int32>(e->Argument), worker, e );          

        }

int SendThem(int index){

            stringstream st;
            st << index;

            //...
            (*this->storing_vars)[st.str()]["index"] =  "testing1";
            (*this->storing_vars)[st.str()]["rs"] = "testing2";
            return 0;
}

as I added the comment in the Sleep(50) line, I believe the problem is that since the thread in the background call the same function, it has a problem to store the data when it's called a lot of times probably not even waiting for the other storing to finish, it's causing an error in the "xhash.h" file, an error that is sanitized by using Sleep(50), but I can't use those because it freezes my UI and also 50 miliseconds is the time I'm assuming it already stored the variable value, but what if it takes longer in slower computers? it's not the right approach.

How do I do to fix that?

I want to be able to UPDATE the unordered_map WITHOUT the use of SLEEP

Thanks in advance.

svick
  • 236,525
  • 50
  • 385
  • 514
Grego
  • 2,220
  • 9
  • 43
  • 64
  • 3
    Is it fair to summarize that the problem is because you are trying to update the same unordered_map from two different threads. And you are attempting to fix it by adding sleep? Is that the issue? – Gangadhar Apr 07 '12 at 18:39
  • 3
    where is your synchronisation mechanism? I see none.... – UmNyobe Apr 07 '12 at 18:41
  • no, I don't want to use Sleep, I'm saying that Sleep is the only way I found to not cause that problem, I want it to be able to update the same unordered_map over and over again by different threads at the same time without the error it throws in the file "xhash" (probably from the unordered_map headers), So I don't want to sleep it I want it to work WITHOUT Sleep – Grego Apr 07 '12 at 18:50
  • @UmNyobe what synchronisation mechanism do you mean? – Grego Apr 07 '12 at 19:00
  • 3
    @Grego : A mutex or a critical section. You're using a thread-unsafe class in a multithreaded context, what did you expect to happen? – ildjarn Apr 07 '12 at 19:06
  • ildjarn, I didn't get the first part of your answer: "a mutex or a critical session" what do you mean? and about the thread-unsafe class, so what would I have to do? isn't it just a issue with the unordered_map? is it a solution to use another type to store the content ? – Grego Apr 07 '12 at 19:16
  • 3
    @Grego: then there's your problem. Would you drive a car without knowing what the steering wheel is? You need to *know what you're doing*. That includes knowing what mutexes and critical sections are, and it means knowing what (if any) multthreading guarantees are given by the data structure you're using – jalf Apr 07 '12 at 21:32
  • @Grego: Get this into your head: There is almost no way to write an initially bug-free multi-threaded program when you know a lot about threads. ___There is certainly no way you can write a bug-free multi-threaded program when you don't even know what a mutex is.___ That deadline is gone. Yes, you might be able to write a program that seems to do what you want because you inserted a call to `Sleep()`, but that's just hiding 90% of the manifestations of the problem. _Of course it will blow up the moment you present it._ – sbi Apr 08 '12 at 15:46
  • That deadline is really gone, stop wasting your time. You seem to have agreed to providing something which you know too little about, and it seems it doesn't work this way. (I'm not surprised.) Now it is time for you to think about `1)` how to deal with the slipped deadline, and `2)` how to find the time to learn multi-threaded programming. – sbi Apr 08 '12 at 15:46
  • @sbi thanks for you answers, but in the answer I typed down there, I didn't need the sleep anymore, I'm predefining the value of the variable so in the thread it will only update instead of creating a new value, so I'm not making a patch. It's working fine. Yea probably mutex is the way to go but what can I do, it's not up to me, it's working successfully. I tested a lot of things and all works fine. So at least for this, it's fine, Theres no Sleep I told hundred of times in my comments. – Grego Apr 08 '12 at 17:02
  • @Grego: No, this is not Ok. Jalf said so, and I said so, and your "answer" got nothing but downvotes. You must not manipulate values from different threads without synchronization and memory barriers. Doing so leads to _UB_. That's threading 101. You could learn it from a book, but you seem to prefer learning it the hard way. – sbi Apr 08 '12 at 18:47
  • what is UB? and also I will start to search how to use those memory barries and synchronization. :) – Grego Apr 08 '12 at 19:18
  • @Grego: _Sigh._ I explained _UB_ in one of my comments. Obviously, you do not read them. I might be wasting my time here. Have a nice day. – sbi Apr 09 '12 at 10:18
  • @sbi Oh man, I'm sorry. :/ It's true I didn't see that comment and now I did read your answer link you sent in it and now I understand it, you are not wasting your time, very well explained and with a little bit of humor, very good. my bad for not seeing it, I really read the comments intently but I have to say I didn't see that one. – Grego Apr 09 '12 at 13:55

3 Answers3

3

You can only modify the standard library containers (including, but not limited to, unordered_map) from one thread at a time. The solution is to use critical sections, mutexes, locks to synchronize access. If you don't know what these are, then you need to know before you try to create multiple threads.

No ifs, buts or why's.

If you have multiple threads, you need mechanism to synchronize them, to serialize access to shared data. Common synchronization mechanisms are the ones mentioned above, so go look them up.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • I know you are right, but the thing is I have deadline, so I have to find the fastest way to make a working solution, but when I'm done with this project I'll absolutely try to understand threads synchronization mechanism, although my way to predefine a value to the variable before calling the backgroundworker works just fine too (the one in my answer below). – Grego Apr 07 '12 at 21:34
  • 5
    Sorry, it doesn't work that way. You can't make a working solution without understanding *how* to make a working solution. Being on a deadline doesn't change that. It just means you're irresponsible, and are going to let your boss/teacher/whatever down – jalf Apr 07 '12 at 21:45
  • Didn't I explain to you in the comment below what I did? Maybe it's not the conventional way, but it's working. and I know what I did, I set the variable to have an initial value so in the thread, it wouldn't have to create, just haad to update this way it doesn't conflict the memory address since it's already predefined. isn't that an explanation? what else do you want ? – Grego Apr 07 '12 at 22:01
  • 4
    @Grego: It is just working for a particular point in time, it may stop working tomorrow when its colder or warmer, or on another computer, or when you are listening to different music. This is what you don't understand, but what you need to understand to make it work. – PlasmaHH Apr 07 '12 at 22:04
  • Why will it? tell me. don't just say words, show me how this will fail. it's easy to just say: "Hey man its not gonna work", show me where it's wrong, show me why it's wrong. – Grego Apr 07 '12 at 22:13
  • @Grego: Just imagine you have two threads. One thread is sleeping your 50ms, the other is held up by the OS for 50ms too, for reasons you can not influence. – PlasmaHH Apr 07 '12 at 22:17
  • No, I solved it without the Sleep(50), I just had to declare a memory point so in the thread it would only have to store and would not have to deal with memory allocation. – Grego Apr 07 '12 at 22:20
  • @Grego: You are aware of that in the canonical implementations of std::unordered_map an insert() of a non-existing key will trigger an allocation on the allocator? – PlasmaHH Apr 07 '12 at 22:26
  • 1
    @Grego : _Use a search engine._ This is all explained a thousand times over in various articles/books/tutorials. Show a little effort. – ildjarn Apr 07 '12 at 22:51
  • 2
    @Grego the problem is that it is not a simple question. Multithreading and synchronization is basically one of the most complex subjects in programming, *and you ask for it to be explained to you in a comment*. At the very least, post a new question just for that. – jalf Apr 08 '12 at 09:34
  • @jalf I can see it's pretty complex haha, I was asked to migrate a PHP/HTML application to C++, but multithread in Ajax it's ridiculously easy. but in C++ not so much, for now I'm ok, but probably later on I'll have another doubt about Thread, and thank you very much for your responses. I'll look them up later, all the one that you told me. Even though my reputation was screwed up by this post, probably because of my answers, it did help me anyway. :) thanks! – Grego Apr 08 '12 at 13:41
  • 4
    @Grego: no, what you're doing with AJAX is not multithreading. It's one thread invoking asynchronous functions. You can do the same in C++ (and it's quite a bit simpler and safer than actually having multiple threads). However, the simplest solution in your case is to just use a single thread, and perform every operation synchronously. Hope that helps. :) – jalf Apr 08 '12 at 13:55
  • @jalf hmm asynchronous functions would be better but I started to learn cplusplus 2 weeks ago to make this program, i'm studying like crazy. and I'm actually learning a lot from you guys here. and I do have to make asynchronously because it's about speed of the data. it makes http connections in each thread, and since the cURL hangs the connection, we have to use threads, even in the cURL website example, it recommends using pthread, but since I'm on visual C++ I chose for its thread system to make it simpler. – Grego Apr 08 '12 at 14:31
  • @jalf and also what should I look for to use asynchronous functions? it sounds better than my way. – Grego Apr 08 '12 at 14:32
  • I think it might be easier to ask a separate question for that. However, since you're not actually using C++, but C++/CLI, you have the entire .NET framework at your disposal (and could easily write your library in C# for example, and then just create a thin C++/CLI wrapper around it. That would also allow you to use the built-in HTTP functionality (which can be used asynchronously) instead of the crufty C-like cURL API. – jalf Apr 08 '12 at 14:47
  • I added a new answer using Mutex provided by the .NET Framework, it's pretty simple to use, if I knew it was that easy I would have implemented it already. :D Thanks guys. @jalf in special. :) – Grego Apr 08 '12 at 20:32
2

After so many votes down I actually started to look for the Mutex, people were talking about here, after a while I find out that it's really simple to use. and it's the correct way as my fellows here told me. Thank you all for the help =D

Here what I did, I just had to add

//Declare the Mutex
static Mutex^ mut = gcnew Mutex;

//then inside the function called over and over again I used mutex
mut->WaitOne();
//Declare/Update the variables
mut->ReleaseMutex();
//Then I release it.

It works perfectly, Thank you all for the helps and criticism. haha

Grego
  • 2,220
  • 9
  • 43
  • 64
-4

I found one solution by predefining the index of the unordered_map I wanna use it, the problem is just creating the index, updating seems to be ok with multiple threads.

for(int i2 = 0; i2 < 30; i2++){



                int index_pos_curr = i2;


                //Start the Threads HERE


                this->backgroundWorker2 = gcnew System::ComponentModel::BackgroundWorker;
                this->backgroundWorker2->WorkerReportsProgress = true;
                this->backgroundWorker2->WorkerSupportsCancellation = true;
                backgroundWorker2->DoWork += gcnew DoWorkEventHandler( this, &MainFacebook::backgroundWorker2_DoWork );
                backgroundWorker2->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &MainFacebook::backgroundWorker2_RunWorkerCompleted ); stringstream st; st << index_pos_curr;

                (*this->storing_vars)[st.str()]["index"] = ""; 
               //This ^^^^^ will initialize it and then in the BackgroundWorker will only update, this way it doesn't crash. :)

                backgroundWorker2->ProgressChanged += gcnew ProgressChangedEventHandler( this, &MainFacebook::backgroundWorker2_ProgressChanged );
                backgroundWorker2->RunWorkerAsync(index_pos_curr);
                Sleep(50); //THE PROBLEM IS HERE, IF I COMMENT THIS OUT it won't work, that's probably because there are a lot of functions trying to add values in the same variable (even though the indexes are differents in each call)
            }
Grego
  • 2,220
  • 9
  • 43
  • 64
  • 3
    just.... try to *understand* the problem, rather than randomly modifying your code until something *seems* to work – jalf Apr 07 '12 at 21:26
  • I did and I explained in the comments, I said that the problem is that the variable was being created at the same time, so if I create it before, it will already have a memory address and then it will only have to store in that address and not create another one, multiple creations of memory at the same time may cause an error depending on how fast it goes to memory or the program sends the command. – Grego Apr 07 '12 at 21:29
  • You still invoke _Undefined Behavior_, only now it manifests in seemingly doing what you want the code to do. Unfortunately, this is one way of _UB_ to manifest itself. Even more unfortunately, it might suddenly start to do something else for no apparent reason. [Thus is the nature of _UB_](http://stackoverflow.com/a/1553407/140719). – sbi Apr 08 '12 at 15:41