When will deadlock occur in this producer-consumer code - concurrency

I was reading about Producer Consumer problem from Operating Systems by William Stallings where following code was given:
+----------------------------------------------------+-------------------------------------------------------+
| Producer | Consumer |
+------------------------------------------------------------------------------------------------------------+
| 1 int n; | 1 void consumer() |
| 2 binary_semaphore mx = 1, delay = 0; | 2 { semWaitB(delay); //wait till first data item |
| 3 void producer() | 3 //is produced |
| 4 { | 4 while (true) |
| 5 while (true) | 5 { |
| 6 { | 6 semWaitB(mx); //continue if producer is not |
| 7 produce(); | 7 //producing |
| 8 semWaitB(mx); //continue if consumer | 8 take(); |
| 9 //is not consuming | 9 n--; |
| 10 append(); | 10 semSignalB(mx);//signal done with consuming |
| 11 n++; | 11 consume(); |
| 12 if (n==1) semSignalB(delay); //unblocks | 12 if (n==0) semWaitB(delay); //block self if |
| 13 //consumer | 13 //no data item |
| 14 semSignalB(mx); //signal done with | 14 } |
| 15 //producing | 15 } |
| 16 } | 16 void main() |
| 17 } | 17 { n = 0; |
| | 18 parbegin (producer, consumer); |
| | 19 } |
+----------------------------------------------------+-------------------------------------------------------+
It then says that (referring to the line numbers in table below):
If consumer exhaust buffer setting n to 0 (line 8), producer has incremented it to 1 (line 11 of table), before consumer checking n and waiting on line 14. Line 14 should have blocked consumer since buffer was exhausted, but it did not, since producer incremented n meanwhile. Worst, consumer can immediately run again to consume non existent item to reduce n to -1 (line 20)
Then it says:
We cannot move the conditional statement inside the critical section as this could lead to deadlock (e.g. after line 8 of above table).
It continues to give different solution.
But I am not able to understand how it will lead to the deadlock. Considering following modified consumer code:
1 void consumer()
2 { semWaitB(delay); //wait till first data item
3 //is produced
4 while (true)
5 {
6 semWaitB(mx); //continue if producer is not
7 //producing
8 take();
9 n--;
10 if (n==0) semWaitB(delay); //block self if
11 //no data item
12 semSignalB(mx);//signal done with consuming
13 consume();
14 }
15 }
16 void main()
17 { n = 0;
18 parbegin (producer, consumer);
19 }
I came up with following:
As you can see, at the end, the values of mx, n and delay are reset to the ones before start. So how this could lead to deadlock? (In fact I feel this could be precise solution.)

It will definitely lead to deadlock. Consider the sequence of operations:
Producer successfully produces 1 item. This results in the following values of the sempaphores:
mx = 1 and delay = 1
Now consumer executes its code and reaches line 10
if (n==0) semWaitB(delay);
because delay is set to 0 because of line 2 of consumer
semWaitB(delay);
The line 10 will block the consumer and at this point we have mx = 0 because of line 6 of consumer semWaitB(mx);
Consumer is already blocked and producer will be blocked due to line 8 semWaitB(mx); as mx = 0. This is a deadlock

Related

How can I compare values of adjacent observations?

I have two datasets that I have appended together in Stata.
There is one variable, say Age in both data sets. I sorted the data so that the ages are in ascending order. I want to delete the observations in each dataset where the corresponding ages don't match.
Dataset 1:
Obs Age
1 7
2 8
3 10
4 5
Dataset 2:
Obs Age
1 10
2 5
3 9
4 7
Combined and sorted in ascending order:
Obs Age
1 5
2 5
3 7
4 7
5 8
6 9
7 10
8 10
So because the ages when sorted don't match up for observations 5 and 6, I want to delete them. Essentially I want a way to loop through pairs of adjacent numbers and compare their values so that I'm only left with pairs with the same ages.
Looping over observations is inefficient and in the vast majority of cases not necessary.
The following works for me:
clear
input age
5
5
7
7
8
9
10
10
end
generate tag = age != age[_n+1] & age != age[_n-1]
list
+-----------+
| age tag |
|-----------|
1. | 5 0 |
2. | 5 0 |
3. | 7 0 |
4. | 7 0 |
5. | 8 1 |
|-----------|
6. | 9 1 |
7. | 10 0 |
8. | 10 0 |
+-----------+
After getting rid of the relevant observations you get the desired result:
keep if tag == 0
list
+-----------+
| age tag |
|-----------|
1. | 5 0 |
2. | 5 0 |
3. | 7 0 |
4. | 7 0 |
5. | 10 0 |
|-----------|
6. | 10 0 |
+-----------+

Fill with values from an earlier time point - Stata

I am trying to generate a variable that is filled using a sequence of values starting at time==1.
The sequence changes everytime the variable rest1w changes from 0 to 1 or vice versa.
Firstly, I think I need to generate x, that is where the sequence restarts (see below example dataset). In my example, this is uniform, but in my full dataset the change varies (i.e. it does not change at every 5th observation).
list time restload trainload rest1w x in 1/15
+-----------------------------------------+
| time restload trainload rest1w x |
|-----------------------------------------|
1. | 1 .1994715 .4780615 0 1 |
2. | 2 .2077734 .471063 0 2 |
3. | 3 .2157595 .4641159 0 3 |
4. | 4 .2234298 .4572202 0 4 |
5. | 5 .2307843 .4503757 0 5 |
|-----------------------------------------|
6. | 6 .2378229 .4435827 1 1 |
7. | 7 .2445457 .436841 1 2 |
8. | 8 .2509527 .4301506 1 3 |
9. | 9 .2570438 .4235116 1 4 |
10. | 10 .2628191 .4169239 1 5 |
|-----------------------------------------|
11. | 11 .2682785 .4103876 0 1 |
12. | 12 .2734221 .4039026 0 2 |
13. | 13 .2782499 .397469 0 3 |
14. | 14 .2827618 .3910867 0 4 |
15. | 15 .2869579 .3847558 0 5 |
+-----------------------------------------+
Secondly, I need to generate a variable load. Which as per below shows how I would like to restart from time==1 everytime the sequence restarts. That is, at the second sequence where rest1w==0, load!=trainload.
The rule is that for each new sequence of 0's the value for load again goes back to the start of time (where time==1). This is demonstrated by the load values in the second sequence of 0's being exactly the same as the first sequence. In other words, where time==1, trainload==.478 then load==.478; BUT where time==11, then load==.478 (the clock essentially restarts for load so time==1) and in sequence where time==15, load==.450 (the same load as for where time==5). This is why I wanted to generate x, as I think I could just use that as my new time variable.
+-----------------------------------------+
| time restload trainload rest1w x load
|-----------------------------------------
1. | 1 .1994715 .4780615 0 1 .4780615
2. | 2 .2077734 .471063 0 2 .471063
3. | 3 .2157595 .4641159 0 3 .4641159
4. | 4 .2234298 .4572202 0 4 .4572202
5. | 5 .2307843 .4503757 0 5 .4503757
|-----------------------------------------
6. | 6 .2378229 .4435827 1 1 .1994715
7. | 7 .2445457 .436841 1 2 .2077734
8. | 8 .2509527 .4301506 1 3 .2157595
9. | 9 .2570438 .4235116 1 4 .2234298
10. | 10 .2628191 .4169239 1 5 .2307843
|-----------------------------------------
11. | 11 .2682785 .4103876 0 1 .4780615
12. | 12 .2734221 .4039026 0 2 .471063
13. | 13 .2782499 .397469 0 3 .4641159
14. | 14 .2827618 .3910867 0 4 .4572202
15. | 15 .2869579 .3847558 0 5 .4503757
+-----------------------------------------+
The below code only gives me an entry for where _n==1:
gen load==.
replace load = restload[_n==1] if rest1w==1
And I like the use of levelsof but haven't been able to get it to work (although it might work once I have generated x, but when using time it doesn't restart the sequence obviously).
gen load=.
levelsof x, local(levels)
foreach l of local levels {
replace load=trainload if rest1w==0
replace load=restload if rest1w==1
}
Thanks for any help!
I ended up cross-posting this on statalist.org and got two workable answers.
http://www.statalist.org/forums/forum/general-stata-discussion/general/1355917-fill-with-values-from-an-earlier-time-point
These were:
gen newtime = 1 if rest1w[_n - 1] != rest1w
replace newtime = newtime[_n - 1] + 1 if newtime == .
gen newload = cond(rest1w == 0, trainload[newtime], restload[newtime])
and...
gen newtime = 1
replace newtime = newtime[_n-1] + 1 if rest1w == rest1w[_n-1]
gen newload = .
replace newload = restload[newtime] if rest1w == 1
replace newload = trainload[newtime] if rest1w == 0

When is pre-decrement applied in a for loop?

I am trying to implement an algorithm that is specified using some C style pseudocode.
The bulk of the algorithm is a for loop:
for (i = 20;i > 0;i -= 2)
{
//...snip
}
It is claimed that the loop runs ten times:
The entire series of modifications is a series of 10 identical double-rounds.
I've ported the algorithm to my own language, and my results do not match the test vectors. So i'm trying to pick apart the minutia of the C-language in order to figure out what i could be doing wrong.
Perhaps the reason my code does not match the result of the test vectors is that it is supposed to only run nine times:
| i | i -= 2 | i > 0 | Perform iteration |
|----|--------|-------|-------------------|
| 20 | 18 | Yes | Yes - 1 |
| 18 | 16 | Yes | Yes - 2 |
| 16 | 14 | Yes | Yes - 3 |
| 14 | 12 | Yes | Yes - 4 |
| 12 | 10 | Yes | Yes - 5 |
| 10 | 8 | Yes | Yes - 6 |
| 8 | 6 | Yes | Yes - 7 |
| 6 | 4 | Yes | Yes - 8 |
| 4 | 2 | Yes | Yes - 9 |
| 2 | 0 | No | No |
If i were to read the if statement logically, it is only executed nine times.
There's still the confusion of why they say it runs ten rounds, but then use 20 as the initial value.
I tried duplicating the logic i see (execute it one less times than documented), but my results still don't match. Unfortunately i don't have access to any functional code to compare my results against a known good implementation. So i may be barking up the wrong tree.
Am i barking up the wrong tree?
The third part of the for condition is executed after the iteration.
The loop runs 10 times with i being 20, 18, 16, 14, 12, 10, 8, 6, 4, 2 for the body of each iteration.
A for loop goes "initialization, test, body, increment, test, body, increment, test, body, etc." The increment isn't applied before the first test.
As an aside, if you want to go from the last to the first element in a for loop but don't want the ugly:
for (let i = arr.length - 1; i >= 0; i--)
You can use:
for (let i = arr.length; i-- > 0;)
Example:
const arr = ['a', 'b', 'c'];
for (let i = arr.length; i-- > 0;) {
console.log(`arr[${i}] is: ${arr[i]}`);
}
Had you used pre-decrement here, the last iteration (which is the first element of the array) would have been missing:
const arr = ['a', 'b', 'c'];
for (let i = arr.length; --i > 0;) {
console.log(`arr[${i}] is: ${arr[i]}`);
}

Stata: Cumulative number of new observations

I would like to check if a value has appeared in some previous row of the same column.
At the end I would like to have a cumulative count of the number of distinct observations.
Is there any other solution than concenating all _n rows and using regular expressions? I'm getting there with concatenating the rows, but given the limit of 244 characters for string variables (in Stata <13), this is sometimes not applicable.
Here's what I'm doing right now:
gen tmp=x
replace tmp = tmp[_n-1]+ "," + tmp if _n > 1
gen cumu=0
replace cumu=1 if regexm(tmp[_n-1],x+"|"+x+",|"+","+x+",")==0
replace cumu= sum(cumu)
Example
+-----+
| x |
|-----|
1. | 12 |
2. | 32 |
3. | 12 |
4. | 43 |
5. | 43 |
6. | 3 |
7. | 4 |
8. | 3 |
9. | 3 |
10. | 3 |
+-----+
becomes
+-------------------------------+
| x | tmp |
|-----|--------------------------
1. | 12 | 12 |
2. | 32 | 12,32 |
3. | 12 | 12,32,12 |
4. | 43 | 3,32,12,43 |
5. | 43 | 3,32,12,43,43 |
6. | 3 | 3,32,12,43,43,3 |
7. | 4 | 3,32,12,43,43,3,4 |
8. | 3 | 3,32,12,43,43,3,4,3 |
9. | 3 | 3,32,12,43,43,3,4,3,3 |
10. | 3 | 3,32,12,43,43,3,4,3,3,3|
+--------------------------------+
and finally
+-----------+
| x | cumu|
|-----|------
1. | 12 | 1 |
2. | 32 | 2 |
3. | 12 | 2 |
4. | 43 | 3 |
5. | 43 | 3 |
6. | 3 | 4 |
7. | 4 | 5 |
8. | 3 | 5 |
9. | 3 | 5 |
10. | 3 | 5 |
+-----------+
Any ideas how to avoid the 'middle step' (for me that gets very important when having strings in x instead of numbers).
Thanks!
Regular expressions are great, but here as often elsewhere simple calculations suffice. With your sample data
. input x
x
1. 12
2. 32
3. 12
4. 43
5. 43
6. 3
7. 4
8. 3
9. 3
10. 3
11. end
end of do-file
you can identify first occurrences of each distinct value:
. gen long order = _n
. bysort x (order) : gen first = _n == 1
. sort order
. l
+--------------------+
| x order first |
|--------------------|
1. | 12 1 1 |
2. | 32 2 1 |
3. | 12 3 0 |
4. | 43 4 1 |
5. | 43 5 0 |
|--------------------|
6. | 3 6 1 |
7. | 4 7 1 |
8. | 3 8 0 |
9. | 3 9 0 |
10. | 3 10 0 |
+--------------------+
The number of distinct values seen so far is then just a cumulative sum of first using sum(). This works with string variables too. In fact this problem is one of several discussed within
http://www.stata-journal.com/sjpdf.html?articlenum=dm0042
which is accessible to all as a .pdf. search distinct would have pointed you to this article.
Becoming fluent with what you can do with by:, sort, _n and _N is an important skill in Stata. See also
http://www.stata-journal.com/sjpdf.html?articlenum=pr0004
for another article accessible to all.

add a new item to vector and shift it remaining part to right

I am trying to put a new item to vector, and shift remaining items. How can I do that ?
Ex
vector -------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 9 | 10 | 15 | 21 | 34 | 56 | 99 |
-------------------------------------------------------
^
new item = 14, it should be added to ^
After insertion,
vector ------------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 21 | 34 | 56 | 99 |
------------------------------------------------------------
^ ^
^-shifted to right by one-^
Check the vector::insert() function.
vector<int> vec ;
// Add elements to vec
vec.insert(vec.begin() + position, new_item);
Use insert.
vector<int> v {1,2,3,5};
v.insert (v.begin() + 3, 4); //v is now {1,2,3,4,5}
You can also insert ranges of elements and other cool stuff, similar to the vector constructor.
if you don't know the exact position you want to insert it then vec.insert() is not going to work well.
vec.push_back(15);
std::sort(vec.begin(), vec.end());