How to break a loop if "break" is inside fork-join? - system-verilog

I need to break a repeat loop, whose break decision is made inside a fork-join block, but my simulator doesn't compile the code that has the following structure.
repeat (10) begin
fork
begin
// do something
end
begin
#(100ms);
break; // compile error
end
join_any
disable fork;
end
I also tried the disable command. I was able to compile, but it didn't break the loop.
repeat (10)
begin : repeat10_loop
fork
begin
// do something
end
begin
#(100ms);
disable repeat10_loop; // try
end
join_any
disable fork;
end : repeat10_loop
Is there a way to use break or disable inside fork-join?

The break and continue statements must be within the same process as the loop statement. The problem with your disable is you incorrectly labeled your loop. Try:
repeat10_loop: repeat (10)
begin

Related

Questions on structuring T-SQL

I'm learning T-SQL and trying to get my head around how to approach it/best practices. Working through some examples, there are three questions I have:
1) Coming from Python, is there a generally agreed upon style guide (something like PEP 8) or approach for laying out T-SQL or is it more like JavaScript where anything goes?
2) When creating stored procedures and functions I see some authors always use a main BEGIN/END block and others don't. At first I thought you need BEGIN/END if you have more than one statement. However, this doesn't seem to be true because I have seen lengthy stored procedures with no main BEGIN/END. Any thoughts on this?
3) Within stored procedures, some authors seem to like to enclose parts of their code in BEGIN/END blocks. I can't see why you'd do this and wonder if I'm missing something. For example:
CREATE PROCEDURE <NAME> (
<Parameter List...>
)
AS
BEGIN
-- Setup:
-- Declare/initialize variables...
BEGIN TRY
BEGIN TRANSACTION
-- Validity check 1:
IF #Param1 ...
BEGIN
-- Do stuff...
END
-- Validity check 2
IF #Param2 ...
BEGIN
-- Do stuff...
END
-- Update - added BEGIN/END after if blocks for clarity
-- Why wrap these statements in a BEGIN/END Block???
BEGIN
--Add the entry
INSERT dbo.JournalClientFamilyChanges (
HouseholdMembersID,
PreviousClientsID,
NewClientsID,
ActionTaken,
Notes,
ModifiedBy,
ModifiedDate
)
VALUES (
#HouseholdMembersID,
#PreviousClientsID,
#NewClientsID,
#ActionTaken,
#Notes,
#ModifiedBy,
SYSDATETIME()
)
SET #success =1;
SET #ErrorStatus ='';
COMMIT TRANSACTION;
END
END TRY
BEGIN CATCH
-- Error handling...
END CATCH
END
Any thoughts appreciated,
--Jim
To answer your question at your own example
IF #Param1 ...
-- Validity check 2
IF #Param2 ...
-- Why wrap these statements in a BEGIN/END Block???
BEGIN
--Add the entry
INSERT dbo.JournalClientFamilyChanges (
HouseholdMembersID,
...
)
VALUES (
#HouseholdMembersID,
#PreviousClientsID,
...
)
SET #success =1;
SET #ErrorStatus ='';
COMMIT TRANSACTION;
END
There is an IF which will call the code below just under certain circumstances. Without the BEGIN ... END this will be valid for the very next statement only. Using BEGIN ... END will see the whole code block covered by the IF condition (the lines with SET and COMMIT).
Try this out:
DECLARE #SomeInt INT=0;
IF #SomeInt=1
PRINT 'Example 1: hello, this is the first line';
PRINT 'Example 1: hello, the next line';
IF #SomeInt=1
BEGIN
PRINT 'Example 2: hello, this is the first line';
PRINT 'Example 2: hello, the next line';
END
For better readability one would use indents. But this is not relevant for the engine. There are some languages using indents as block marker though, others use paranthesis or any kind of brackets. T-SQL uses BEGIN ... END. Sometimes people use this in larger procedures just to allow collapsing (like the #region in C#)
IF #SomeInt=1
PRINT 'Example 1: hello, this is the first line';
PRINT 'Example 1: hello, the next line';
IF #SomeInt=1
BEGIN
PRINT 'Example 2: hello, this is the first line';
PRINT 'Example 2: hello, the next line';
END
update
Just to reflect the comments below: The OP changed the initial question in a way, that the BEGIN ... END is no longer connected to the IF. So the question shoudl be: Why would one use BEGIN ... END without any functional reason?.
The answer for this is
To mark some lines of code as a "block"
... thus emphasising the functional unit
Collapsing is a nice side-effect

How do I exit this function?

Essentially its built like so:
.If
..other stuff
.Else
..For
...For
....If (this is where I need to be able to break out of the whole thing)
I've tried using return, and break, but they just are not working for whatever reason. I added in a ticker and it appears that the break command isn't working?
The code just continues going on and repeating the for loop even AFTER it is 'broken' in the If statement.
My function is only about 150 lines long, so I've been able to study it closely, and this seems to be where the problem is.
If you have
for (...)
for (...)
if (true)
break;
end
end
you'll only break out of the inner loop. But, of course, the outer loop will continue as normal!
Breaking out of nested-loops is one of the very few reasonable use cases for a goto. However, MATLAB does not have a goto, so you'll have to repeat yourself in some way or another:
for (...)
for (...)
if (condition)
break;
end
if (condition)
break;
end
An equally ugly yet common and less verbose way:
try
for (...)
for (...)
if (condition)
error(' ');
end
end
catch %#ok
(code you want to be executed after the nested loop)
end
or, to be pedantic,
breakout_ID = 'fcn:breakout_condition';
try
for (...)
for (...)
if (condition)
error(breakout_ID, ' ');
end
end
catch ME
% graceful breakout
if strcmp(ME.Identifier, breakout_ID)
(code you want to be executed after the nested loop)
% something else went wrong; throw that error
else
rethrow(ME);
end
end
Or you build a (nested) function containing just that nested loop, and use return to break out. But that may not always give the most "obvious" code structure, as well as cause you to have to write lots of boilerplate code (subfunction) and/or have unforeseen side effects (nested functions), so...
Personally, I favor the try/catch above.

BREAK statement in PL/pgSQL

How to have the break statement in PostgreSQL? I have the structure like this:
for()
{
for()
{
if(somecondition)
break;
}
}
As per my understanding it should only break the inner for loop?
There is no BREAK in PL/pgSQL.
EXIT terminates the loop.
CONTINUE continues at the next iteration of the loop.
You can attach a <<label>> to loops and add it as parameter to each of these commands. Then you terminate / continue the labeled loop. Else, it concerns the inner loop.
RETURN exits from the function (so not applicable in a DO statement).
All of this applies to procedural elements of PL/pgSQL, not SQL.
Code example using all three:
Loop in function does not work as expected
Note, that: Yes! you need the "WHEN", even if you end up (like me ;-)) with something like
LOOP
...
IF l_my_var = 'some condition' THEN
-- this is ok, bla
IF l_debug_level >= 2 THEN
RAISE NOTICE 'debug 2: skipping a duplicate %, l_my_var;
END IF;
-- do something
CONTINUE WHEN TRUE; -- https://stackoverflow.com/questions/15173194/break-statement-in-pl-pgsql
ELSE
-- do something
END IF;
...
which looks somewhat twisted with both IF and WHEN.
Remark to the editor:
One could make the link behind "CONTINUE" more precise: https://www.postgresql.org/docs/9.6/plpgsql-control-structures.html#AEN66440

How to purposely test errors in a transaction?

I have a stored procedure that has several transactions in a loop:
WHILE #COUNT < #MY_NUM
BEGIN
BEGIN TRANSACTION
-- DO STUFF HERE
IF(##ERROR != 0)
BEGIN
ROLLBACK TRANSACTION
BREAK
END
COMMIT TRANSACTION
END
I would now like to test whether or not my ROLLBACK TRANSACTION and BREAK logic will work by purposely introducing an error to the loop after a certain number of runs and look at the data.
Furthermore, I run these stored procedures from a shell script. So, I would like to test by using Ctrl + C in the middle of a run. Will this work? If not, how can I purposely introduce an error?
Thanks
You could do one of the following:
Intentially cause an error like Divide by zero
Use RaiseError()
You can to use print:
WHILE #COUNT < #MY_NUM
BEGIN
BEGIN TRANSACTION
print 'BEGIN TRANSACTION'
-- DO STUFF HERE
print '-- DO STUFF HERE'
IF(##ERROR != 0)
BEGIN
ROLLBACK TRANSACTION
print 'ROLLBACK TRANSACTION #MY_NUM: %1!',convert(varchar,#MY_NUM)
BREAK
END
COMMIT TRANSACTION
print 'COMMIT TRANSACTION'
END
Here it's link to documentation.

SQL GOTO statement in a script with multiple GO

I need to exit a SQL script without an error if a certain condition holds true. I've read that 1 solution would be to raiseerror with error code 20+ and with log parameter. But the limitation for that is that i can execute that only as an admin and the connection to the db will be aborted.
Also, I tried using GOTO and jump to the end-of-the-script, but it doesnt work, because I have multiple GO in the middle of the script. Is there a another solution?
IF <some condition>
BEGIN
GOTO Finished;
END
GO
Finished:
SELECT 'Done'
Thanks!
goto cannot jump past a go. You'd have to retest the condition in each block:
IF NOT <some condition>
BEGIN
...
END
GO
IF NOT <some condition>
BEGIN
...
END
GO
IF NOT <some condition>
...