multiple operators sharing 3 tools, how to avoid deadlock? - deadlock

I would like to ask some suggestions to solve this particular deadlock:
3 operators, each is given 2 of 3 different materials at random: 1, 2, 3
3 tools, each material needs a different tool to process by an operator.
material 1 needs tool 1
material 2 needs tool 2
material 3 needs tool 3
Each operator needs to wait for the proper tools to process the materials.
i.e. If an operator has taken material 1,2, he needs tool 1,2
A deadlock may happen:
operator 1 has taken material 1,2, waiting for tool 1,2
operator 2 has taken material 2,3, waiting for tool 2,3
operator 3 has taken material 3,1, waiting for tool 3,1
None of the operator can acquire both tools, what should the operator do?
Proposal
Create a global variable to record the recent 6 materials taken by the operators. If each material appeared twice (example [1,3,1,2,2,3]), then the last operator should keep abandoning the last material until no all materials appear twice (example [1,3,1,2,2,1])?
Will this work? what if I have 10 operators with 3 tools and 3 materials. Any suggestion will help.

So how it works is that an operator would take one of the tools, and then the second one. if the second one wasn't available. then it would let the first one go too ( it will put the first tool back and make it free and available for other operators). This way, the other operator that is waiting for that tool would take it and the deadlock won't happen.
int toolx=0; // operator has no tool x
int tooly=0; // operator has no tool y
pthread_mutex_lock(&tool_mutex);
// loop if toolx and tooly are not aquired
while ((toolx + tooly)!=2){
//drop tool x
if (toolx == 1) {
toolbox[mat_x] ++;
toolx -- ;
pthread_cond_signal(&cond_tool);
}
// drop tool y
if (tooly == 1) {
toolbox[mat_y] ++;
tooly -- ;
pthread_cond_signal(&cond_tool);
}
// wait on tool x
while (toolbox[mat_x] == 0) {
pthread_cond_wait (&cond_tool,&tool_mutex); // wait
}
// wait complete and take tool x
toolbox[mat_x] --;
toolx ++ ;
//try take tool y
while (toolbox[mat_y]== 0) { // if other is taking tool y
if (toolx == 1) { //if operator is holding toolx.
toolbox[mat_x] ++;
toolx -- ; // put back tool x
pthread_cond_signal(&cond_tool);
}
pthread_cond_wait (&cond_tool,&tool_mutex); // wait on tools
}
// take tool y
toolbox[mat_y] --;
tooly ++;
}
pthread_mutex_unlock(&tool_mutex);

Related

Sabre Scribe Scripting Specifically Looping

Anybody have any tips for looping, and continue? For example, I placed about 2500 pnrs on a queue, and I need to add a remark to each of them. Is it possible for a script to add the remark then move to the next pnr?
For example, I placed about 2500 pnrs on a queue, and I need to add a remark to each of them. Is it possible for a script to add the remark then move to the next pnr?
Loops are supported in Scribe but have to be built manually by creating your own iteration variables and breaking the loop manually when you know the work is complete.
What you are describing is definitely possible, but working in queues can be difficult as there are many possible responses when you try to end the PNRs. You'll have to capture the response to detect whether you need to do something else to get out of the error condition (e.g. if a PNR warning indicates you have to double-end the record).
If possible, its likely simpler to work off the queue by collecting all PNR locators and then looping through that list, adding your remarks, and then ending the PNRs. You'll still have to capture the response to determine if the PNR is actually ended properly, but you won't have to deal with the buggy queue behavior. A basic Scribe loop sample is below. Note that I haven't been a Scribe developer for a while and I did this in Notepad so there might be some errors in here, but hopefully it's a good starting point.
DEFINE [ROW=N:8] ;iteration variable/counter
DEFINE [LOCATOR_FILE=*:60] ;File Path
DEFINE [TEMP_LOCATOR=*:6] ;pnr locator variable, read from the temp file
DEFINE [BREAK=*:1] ;loop breaking variable
OPEN F=[TEMP_LOCATOR] L=0 ;open the file of locators
[BREAK] = ""
[ROW] = 0
REPEAT
[ROW] = [ROW] + 1
[TEMP_LOCATOR] = "" ;Reset temp locator variable, this will break our loop
READ F=[LOCATOR_FILE] R=[ROW] C=1 [TEMP_LOCATOR]
IF $[TEMP_LOCATOR] = 6 THEN ;test length of locator, if this is 6 chars, you have a good one, pull it up and add your remark
»"5YOUR REMARK HERE"{ENTER}«
»ER{ENTER}«
;trap errors
READ F="EMUFIND:" R=0 C=0 [TEMP_LOCATOR] ;read for the locator being present on this screen, which should indicate that the ER was successful - you'll have to trap other errors here though
IF [#SYSTEM_ERROR] = 0 THEN ;this locator was found, ER appears successful
»I{ENTER}« ;Ignore this PNR and move to the next one
ELSE
[BREAK] = "Y" ;error found afeter ER, break loop. Maybe show a popup box or something, up to you
ENDIF
ELSE ;No locator found in file, break the loop
[BREAK] = "Y"
ENDIF
UNTIL [BREAK] = "Y"
CLOSE [LOCATOR_FILE]

With or without the Keira3 editor, is there a way to tie a ".levelup" command or a level-up reward to a quest?

I'm a novice and am working on learning the basics. I have no experience in coding.
I'm trying to make a world for myself and my friends that features quest rewards being the sole way to gain levels, and in full increments - exactly like milestone leveling in Dungeons and Dragons.
Is there a way to level up a character, or have an automated ".levelup" command be used on a character, triggering when that player completes a (custom) quest? Additionally, is this something that can be done in Keira3? Or will I need to use other tools?
I've tried granting quest reward consumables that use the spells 47292 and 24312 (https://wotlkdb.com/?spell=47292 and https://wotlkdb.com/?spell=24312) but those appear to just be the visual level-up effects.
There are multiple ways to achieve this. The most convenient way that I can think of, is to compile the core with the eluna module: https://github.com/azerothcore/mod-eluna
It allows for scripting with the easily accessible Lua language. For example, you can use the following code:
local questId = 12345
local questNpc = 23456
local maxLevel = 80
local CREATURE_EVENT_ON_QUEST_REWARD = 34 --(event, player, creature, quest, opt) - Can return true
local function MyQuestCompleted(event, player, creature, quest, opt)
if player then -- check if the player exists
if player:GetLevel() < maxLevel and quest = questId then -- check if the player has completed the right quest and isn't max level
player:SetLevel( player:GetLevel() + 1 )
end
end
end
RegisterCreatureEvent( questNpc , CREATURE_EVENT_ON_QUEST_REWARD , MyQuestCompleted)
See https://www.azerothcore.org/pages/eluna/index.html for the documentation.

I need help for gamemaker 2.3

Pls help me
A few weeks ago it came out of gamemaker 2.3, practically in the gamemaker language they changed the scripts into functions, but now after converting the files to be able to reopen them, I double-checked all the scripts and etc but anyway when I start it it remains a black screen, however it doesn't give me any compilation errors or whatever, what could be the problem?
Ps.
I might sound stupid, but if someone has the same program as me I can pass the project to them so they can see the scripts for themselves, so basically it's just the base and there is only the script to make the player walk and for collisions, I know that no one would want to waste time, but I ask the same
Its possible that your code is stuck in an infinite loop, here's an example of what that might look like:
var doloop = true
while(doloop == true){
x += 1
y += 1
}
the "doloop" variable is never changed within the while loop, so it is always equal to true and the loop never ends. Because the code never finishes looping, it can never get around to drawing anything, so you end up with a black screen. The easiest way to check for these is to put a breakpoint/debugging point at the beginning and just after every while/for/do/ect loop and debug it. e.g. (I am using asterisks "*" to represent breakpoints)
var doloop = true
* while(doloop == true){
x += 1
y += 1
}
*
When you get to one of the loops remove the first breakpoint and hit the "continue" button in the debugger. If it (it being the computer) takes an longer than it should to hit the second breakpoint (as in, you wait for a ten seconds to or two minutes (depends on how complex the code is) and it still hasn't hit the second breakpoint), then you should replace the breakpoint at the beginning of the loop to check and make sure it is still in there. If it is still in the loop, then that is likely where the code is getting stuck. Review the loop and everywhere any associated variables are set/changed, and you should be able to find the problem (even if it takes a while).
Majestic_Monkey_ and the commentors are correct: use the debugger. It's easy and it's your friend. Just place a red circle on the very first line of code that runs, and click the little bug icon and you can step through your code easily.
But to address your specific issue (or if anyone in the future has this issue): scripts have changed into files that can have many functions. Where you used to have
//script_name
var num = argument0 + argument1;
return num;
You would now have
function script_name(a, b) {
var num = a + b;
return num;
}
All you have to do is create a decleration for your new function:
function my_function_name(argument_names, etc...)
Then wrap all your old code in { }, and replace all those ugly "argument0" things with actual names. It's that easy. Plus you can have more than one function per script!

XC8 builds font tables from top ROM

I wrote a barebone progran template in XC8 (1.37) that I use to develop and test new GLCD functions for the 18F family. Programming is done via a PICkit3. Since I need to quicky reprogram several times the code it is really important that programming is faster as much as possible.
Tipically, the code size is around 2K and it takes less than 10 sec to program,
Everiything is fine until I must use a font table, defined as:
const char font8[] = {....
Now, with just $400 bytes added, the compiler place the table at the ROM's end and the programming of 64K memory takes more than 1 minute.
Is there any way to avoid this?
I tried to manually limit the memory range in the MPLABX options, but this is annoying and a little unsafe (sometimes part of code is truncated).
A while back I had to write some code for emissions testing, where I needed to copy data between extreme ends of RAM. To do that I needed to specify the exact memory addresses. You can also use the C extension __at() construct. http://ww1.microchip.com/downloads/en/DeviceDoc/50002053F.pdf#page=27
int scanMode __at(0x200);
const char keys[] __at(123) = { ’r’, ’s’, ’u’, ’d’};
int modify(int x) __at(0x1000) {
return x * 2 + 3;
}

I don't fully understand when these recursive calls return

I understand simple recursion code but sometimes when it gets a bit complicated. I get lost and can't really follow the code.
For example of the follow code(an anonymous wrote it):
void reversetree(struct node* head)
{
//first check for the exception whether does it even exit or not
if(head==NULL)
return ;
reversetree(head->left); //reverse call for left child
reversetree(head->right); //same reverse call for right child
//now next these steps will swap the children
struct node* temp=head->left;
head->left=head->right;
head->right=head->left;
//now exit the function and you are done :)
}
6
/ \
3 4
/ \ / \
1 2 8 9
Lets say if the binary tree looks like this,can someone do a step by step logic for me please? For my understanding, it first checks to see if the root exists, if it does then it call the function again of the left child until there is no more left child? so when the the code that swaps it ever get called? and when does it start calling the function with the right child? Sorry I am not too bright with recursions.
Usually when dealing with recursion people tend to tell you to do it with pen and paper. Its a great exercise, but I find it easier to do it these ways:
First way to look at it
There is no difference between using a recursive function and a different function that performs the same job. They both do their job and return so that your code resumes on the next line.
Imagine you have a working function, reversetree_external that reverses a whole tree so that you could write your function this way without recursion:
void reversetree(struct node* head)
{
if(head==NULL)
return ;
// switch left and right
struct node* temp=head->left;
head->left=head->right;
head->right=temp; // There was an error here
// Reverse subtrees
reversetree_external(head->left);
reversetree_external(head->right);
}
So everything you need to convince yourself of is that given an argument like:
6
/ \
3 4
/ \ / \
1 2 8 9
Turns into the following before reversetree_external reverses the two subtrees:
6
/ \
4 3
/ \ / \
8 9 1 2
If you only pass one of right and left it would turn that level before using reversetree_external to not do anything.
If you pass it a leaf node, eg. 8 the result is the same 8 (with the null pointers swapped) and reversetree_external won't do anything since it will be given NULL both times.
In fact You can see that reversetree can do the same thing as reversetree_external so instead of relying on it you can just use reversetree itself.
Second way to look at it
Now, it's good to look at this in two ways so do it in reverse, eg. start with NULL.. eg. the left node of 8, then a leaf, then a tree that uses the leaves and then a full tree using the subtrees we have calculated in advance.
input result
NULL NULL
8 8
9 9
1 1
2 2
4 4
/ \ / \
8 9 9 8
3 3
/ \ / \
1 2 2 1
6 6
/ \ / \
3 4 4 3
/ \ / \ / \ / \
1 2 8 9 9 8 2 1
So in place of doing the recursion in my mind I just use the previous result in the results which you know the same function would do. eg. I switch the 3 and 4 as the procedure would use and the two recursions is just the same transformation as the subtree done before.
The first way is just how to read recursive code, the second way is perhaps the easiest and how you can make your own recursive functions with ease. You start with the base case(es) and test them, then add a default case how to do a slightly more complex problem into a smaller similar problem that eventually ends up being a base case.
If the root does not exist, the function quits because it has no children.
Yes, the processor will then follow the chain of left children until it runs out, then the left children of the last node's right child ...
For the tree shown, here's what will happen:
Reverse node 6:
Reverse node 3:
Reverse node 1:
Reverse NULL
Reverse NULL
Swap 1's links to NULL and NULL
Reverse node 2:
Reverse NULL
Reverse NULL
Swap 2's links to NULL and NULL
Swap 3's links to 1 and 2
Reverse node 4:
Reverse node 8:
Reverse NULL
Reverse NULL
Swap 8's links to NULL and NULL
Reverse node 9:
Reverse NULL
Reverse NULL
Swap 9's links to NULL and NULL
Swap 4's links to 8 and 9
Swap 6's links to 3 and 4
It would run a bit faster with a test for NULL before each call.
The swap step could go before the recursive calls, without affecting the speed or result.

Resources