Sometimes when I'm writing XLANG/s code in an expression shape, it would be more readable if I could just use a temporary variable within the scope of that one code block. I hate to clutter up the entire orchestration with a variable declaration. Is there a way to declare a variable within an expression shape?
So, it appears that the correct way to do this is to use a scope shape and to put the expression shape inside it. You can set the scope shape's transaction type to "None" if you don't need any special transaction handling. The scope shape can have variables associated with it (or messages or correlation sets), and they are visible only to the shapes within it.
If you check out the XLANG/s code that's generated when you use a scope shape you'll see it uses a scope keyword. It turns out that you can put the same code within your expression! So you'd do something like this:
scope
{
System.String tempString;
body
{
tempString = someCalculation;
// etc.
}
}
Related
If I have the following code:
// objective C++ code .mm
id<MTLTexture> texture = ...;
void* ptr = (void*)CFBridgingRetain(texture);
share_ptr_with_native_code(ptr);
[texture do_stuff]; // is this valid?
// native code .cpp
void share_ptr_with_native(void* ptr)
{
ptr->do_stuff();
CFBridgingRelease(ptr);
}
Will texture be valid and retained by ARC again after the call to share_ptr_with_native()?
Other than various errors in your code snippet, yes, the line in question is valid. ARC continues to maintain its own strong reference to object while it's still in use in the top code, in addition to the one that you become responsible for. CFBridgingRetain() has a +1 effect on the retain count of the object, hence "retain" in its name.
Even everything said is right, it would be nicer if you change your
CFBridgingRelease(ptr);
to
CFRelease(ptr) .
__bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.
You are responsible for calling CFRelease or a related function to relinquish ownership of the object.
Taken from https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html.
Let's consider a complex structure in fortran
TYPE ComplexStrType
! Static as well as dynamic memory defined here.
END TYPE ComplexStrType
Defined a physical space (allocated on the stack memory I think) to use two variables of ComplexStrType:
TYPE(ComplexStrType) :: SomeComplexStr
TYPE(ComplexStrType) :: AnotherComplexStr
TYPE(ComplexStrType),POINTER :: PointerComplexStr
Then, I use SomeComplexStr to define a few stuff in the stack and to allocate a big space in the dynamic memory.
Now, suppose I want to point AnotherComplexStr to SomeComplexStr and forget space I have defined in the stack memory to AnotherComplexStr. To do that I use a simple but useful trick which converts some variable in a Target:
FUNCTION TargComplexStr(x)
IMPLICIT NONE
TYPE(ComplexStrType),INTENT(IN),TARGET :: x
TYPE(ComplexStrType),POINTER :: TargComplexStr
TargComplexStr => x
END FUNCTION TargComplexStr
And then I point PointerComplexStr to SomeComplexStr:
PointerComplexStr => TargComplexStr(SomeComplexStr)
Finally, I do AnotherComplexStr equal to PointerComplexStr:
AnotherComplexStr = PointerComplexStr
After that, it's supposed SomeComplexStr as well AnotherComplexStr are pointing to the same static and dynamic memory.
The thing is:
How can I free the space used by AnotherComplexStr used when I defined it at the beggining?
How do you recomend me nullify the pointers?
Is that practice safe, or do I have to expect some strange memory leaks on the execution?
If it's possible, how can I point the "pointed variable" to its original form? (Just in case I have to use it again as normal variable)
NOTE: It's useful because at the execution we can be decided if we want to use AnotherComplexStr as what it is, a complex and allocated structure, or we can switch it to be treated as a pointer and points it to another thing which already has the information we need. If there is another and easy way to do that, please tell me.
The "trick" that you are using in TargComplexStr does not work the way you think - that function offers nothing useful over simple pointer assignment.
You can associate a non-TARGET actual argument with a TARGET dummy argument, as you are doing, but when the procedure with the TARGET dummy argument completes, any pointers that were associated with the dummy argument become undefined (F2008 12.5.2.4 p11).
(Pointers can only be associated with targets, therefore something that isn't a target cannot have a pointer associated with it.)
This means that the result of the function is a pointer with undefined association status. It is not permitted to return a pointer with undefined association status from a function (F2008 12.6.2.2 p4).
The pointer assignment statement would then make PointerComplexStr become an undefined pointer. PointerComplexStr is then referenced in the assignment to AnotherComplexStr. It is not permitted to reference a pointer with undefined association status (F2008 16.5.2.8 p1).
Intrinsic assignment creates a copy of a value. This is the case even if the object on the right is a pointer - a copy of the value of the target of that pointer is created. Intrinsic assignment does not, at the level of the top data object being assigned[1], make one variable reference the storage of another. As far as I can tell, the intent of your entire example code could be replaced by:
AnotherComplexStr = ComplexStr
If you are trying to do something different to that, then you need to explain what it is that you are trying to do.
[1]: If the type of an object being assigned is a derived type that has a pointer components, then the definition of the value of the object includes the pointer association status of the pointer component, but not the value of the target of the component itself (F2008 4.5.8).
I have a specification of a function that acts like a constructor. The specification of the function is
function Create_Controller return Type_Controller;
Also, in the specification file, I have the Type_Controller type, which is an access. I copy the relevant fragment:
type Type_Controller_Implementation;
type Type_Controller is access Type_Controller_Implementation;
So, this is what I've attempted:
function Create_Controller return Type_Controller
is
My_Controller : aliased Type_Controller_Implementation;
begin
return My_Controller'Access;
end Create_Controller;
I tried to compile the program without the aliased keyword, but then, the compiler says:
prefix of "Access" attribute must be aliased
So, I put the aliased keyword and the compiler now suggests that I should change the specification:
result must be general access type
add "all" to type "Controlador_De_Impresion" defined at controller.ads
The problem is that I'm not allowed to change the specification. I've read the chapter about access types in the Ada Programming Wikibook, but I still don't understand why my code doesn't work. What am I doing wrong?
The implementation of the Create_Controller function body is incorrect. Were it to work as coded, you'd be returning a pointer to a variable local to that function body's scope...which would be immediately lost upon returning from the function, leaving you with an invalid pointer.
No, an instance of the type needs to be allocated and returned. If there's no explicit initialization that needs to occur you can simply do:
return new Type_Controller_Implementation;
If there is some initialization/construction that has to occur, then:
function Create_Controller return Type_Controller
is
My_Controller : Type_Controller := new Type_Controller_Implementation;
begin
-- Set fields of My_Controller
...
return My_Controller;
end Create_Controller;
When you declare an access type as access T, you're saying that "this is a pointer to a T and it must point to objects of type T allocated from a pool". (That is, allocated with a new keyword.) When you declare an access type as access all T, you're saying that it can point either to a T allocated from a pool, or to an aliased variable of type T.
If the type is declared as access T and you can't change it, then all access values of the type have to point to something allocated with new. You can't make it point to a variable (even to a "global" variable that isn't located on the stack).
The reasons for this are historical, I think. The first version of Ada (Ada 83) only had "pool-specific types." You couldn't make an access value point to some other variable at all, without trickery. This meant that a compiler could implement access values as indexes into some storage block, or as some other value, instead of making them the actual address of an object. This could save space (an access value could be smaller than an address) or allow more flexibility in how pool memory was managed. Allowing access values to point directly to objects takes away some of that flexibility. I think that's why they decided to keep the old meaning, for backward compatibility, and require an all keyword to indicate the new kind of access.
If you capture a strong reference to self under ARC in an objective-C style block, you need to use a __weak pointer to avoid an ARC "retain cycle" problem.
// Right way:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
I really don't know what a retain cycle is, but this answer describes it a bit. I just know you should use a __weak pointer for Objective-C style blocks. See Avoid Strong Reference Cycles when Capturing self.
But my question is, do I need to create a weak pointer when capturing self under a C++ <functional> block?
- (void)configureBlock {
self.block = [self](){
[self doSomething]; // is this ok? It's not an objective C block.
}
}
C++ lambdas can captured variables either by value or by reference (you choose when you declare the lambda how to capture each variable).
Capturing by reference is not interesting, because references to local variables become invalid after you leave the variable's scope anyway, so there is no memory management issues at all.
Capturing by value: if the captured variable is an Objective-C object pointer type, then it gets interesting. If you are using MRC, nothing happens. If you are using ARC, then yes, the lambda "retains" captured variables of object pointer type, as long as they are __strong (not __weak or __unsafe_unretained). So, yes, it would create a retain cycle.
I have the following code
$pageName = "test";
$Container = {};
I like to set a property of $Container by a variable. I tried $Container.set("test", $pageName);. It didn't raise any errors, but $Container.test or $Container.get("test"); display nothing.
How do I fix it?
The problem is that set is the wrong method. You need to do a put. Remember - Velocity is calling the Java methods. There is no "set" method on a Map object.
Specifically, you can do
$Container.put("test", $pageName)
Now, one weird thing is that this will print "true" or "false" in the page, since the Map.put() method returns a boolean. So I always do
#set($dummy = $Container.put("test", $pageName))
which does the put and stores the result in another reference (which you can then ignore) instead of rendering it to the page.
Hey I ran into the same problem is the "true" or "false" printed on the page, and there is a simpler way to handle it. What I did is a little weird, and I did it Confluence, which of course uses Velocity under the covers. I mention that because I understand Velocity can be used in may different applications.
With a Confluence user macro, I check for a previously created attribute on the req variable, the request variable, i.e. "myPageVars". Then I use the put method to put a new key-value pair, based on the macro parameters. By using the $! prefix, rather than just $, the output isn't sent to the screen.
...
$!req.getAttribute("myPageVars").put( $paramKey, $paramValue )
...
I'm somewhat new to Velocity, so I can't guarantee this will work in every context, but it seems syntactically easier than the whole #set ($dummy etc. line.