Sometimes, we need to update one field of entry.value.
the thread safe way to do that is construct a new entry.value and
use put method to update. that is said, I need to make deep copy
of original value even though I just do some little modification.
Can I do this update like
map[key].field = fieldValue;
Hash map returns an entry safely, but assignment of a field is out of scope of the map. So, you should do something here for thread safety. Your code is equivalent to:
Entry entry = map[key];
entry.field = fieldValue;
Obviously the field assignment operator doesn't know anything about the map.
Maybe a lock for the entry itself is needed. If it is just an assignment, then volatile.
Related
I have a variable decodedToken (type: struct), and I access one of its values called "Claims" through a type assertion:
claims := decodedToken.Claims.(jwt.MapClaims)
I then loop through the claims (type: map[string]interface{}), and modify its values in place:
for key := range claims {
claims[key] = "modified"+key
}
Hence, I expect that the original decodedToken variable would be unchanged, since I have just performed an operation on the claims variable. However, decodedToken is also changed to my modified value.
My question is why is this so, and how do I leave the decodedToken untouched?
Since claims is a reference type, like a map or slice.
The solution is make a deep copy of any referenced data. Unfortunately there are no universal way to make a deep copy of any map in Go. So you should make your own.
Or more practical way to do your job is making a new object(variable) to contain the modified decodedToken.
Also, it's not good to iterated a map and modify its value in a same statement.
To be fair, I cannot be entirely sure the title correctly describes the problem I am having, as it merely mirrors my current understanding of Ada as it is.
The Problem
I have a function:
function Make_Option (Title : String) return Access_Option is
O : aliased Option := (
Title_Len => Title'Length,
Title => Title);
begin -- Make_Option
return O'Unrestricted_Access;
end Make_Option;
This function is supposed to create a new menu option for the user, that may in turn be inserted into a menu (one that you might see in a terminal-based environment). You are all probably sighing, as quite evidently, the O variable would be deallocated at the end of this function (from my current understanding). As such, using the Unrestricted_Access here is just plain stupidity, but it mirrors the result of what it is I am trying to accomplish (as this code indeed does compile successfully).
The Access_Option is defined as following:
type Access_Option is access all Option;
The idea is that with an access to the option, which in turn is a discriminated record, is that we can store it within an array-like structure (as the object itself varies in size).
Beyond doubt, it would be nice if we could instead use the Access attribute for this, as the compiler would then make sure the lifetime is long enough of the O variable we are referencing, but as the lifetime as a matter of fact only exists til the end of the Make_Option function, we are presented with the following:
non-local pointer cannot point to local object
What I am then asking, is: how would I go about having a function to create Access_Options for me? Is such a thing even possible, or am I doing it all wrong? To clarify, what I am trying to do is create a neat way for filling an array with references to discriminated records, that I can then dereference and use.
Thought Process
I personally have not tried too many things, more than think about solutions that may be plausible for the problem. And, frankly, rather than going crazy of working makeshift solutions, it would be nice to have a solution that works for large-scale applications too, without messing up the code base to bad.
Would you perhaps have some sort of object queue to handle it? Does Ada even deallocate resources automatically in the first place? Gah. I am confused.
Would it, in fact, be possible to somehow place the O variable outside of the scope for deallocation to then manually deallocate it later?
Given the example you show above a much simpler approach is to simply make an array of Unbounded_String:
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_Io;
procedure Str_Arrays is
type Arr is array(1..10) of Unbounded_String;
A : Arr;
begin
for S of A loop
S := To_Unbounded_String("Hello World!");
end loop;
for S of A loop
Put_Line(To_String(S));
end loop;
end Str_arrays;
Don't try that.
There are two alternative options:
1) Use Ada.Containers.Indefinite_Vectors instead of a plain array.
2) Give your record discriminant a default value. Then you can store it in a plain array.
You seem to be reinventing the bounded string. Alternatives include
Using an instantiation of Ada.Strings.Bounded.Generic_Bounded_Length
Using Ada.Strings.Unbounded
Using an indefinite container (Ada.Containers.Indefinite_*) to hold type String
I was wondering how to bind values where the source of the bind could be null.
I have a property:
private ObjectProperty<Operation> operation = new SimpleObjectProperty<>(null);
I also have a text field:
#FXML
private Text txtCurrentOperation;
I would like to bind the textProperty of the field to the value of the operation object.
My first thought was to use FluentAPI with its when/then/otherwise construct, but it is eagerly evaluated so the solution:
Bindings.when(operation.isNotNull())
.then("null")
.otherwise(operation.get().getName()));
will throw a NPE, because the parameter of otherwise is evaluated no matter what the result of the when.
My next idea was to use lambda somehow:
txtCurrentOperation.textProperty().bind(() ->
new SimpleStringProperty(
operation.isNotNull().get() ? "Null" : operation.get().getName()
));
But the bind has no lambda enabled solution. (Later I realized that it couldn't have, becasue the real work goes backward: the change of the binded object (operation) will trigger the update of the binder (the field text property).)
Some articles I found suggested to use an "extremal" value for the property instead of null. But Operation is a complex and heavy weight component so it is not trivial to construct an artifical instance to represent null. Even more, this seems to me boilercode, something the binding mechanism is designed to help eliminating.
My next try was to logically swap the binding direction and add listener to the operation property and let it update the field programatically. It works and rather simple as long as the need of update only depends the operation object instances:
operation.addListener((e) -> {
txtCurrentOperation.setText(operation.isNull().get() ?
"Null" : operation.get().getName());
});
operation.set(oper);
It is relatively simple, but doesn't work: it throws "A bound value cannot be set." exception and I don't see why is the text property of the control regarded as bound.
I ran out of ideas. After much searching, I still cannot solve the simple problem to update a text field differently based on whether the source is null or not.
This seems so simple and everyday problem, that I am sure I missed the solution.
If a 3rd party library is an option, check out EasyBind. Try something like this:
EasyBind.select(operation)
.selectObject(Operation::nameProperty)
.orElse("null");
There's also a JavaFX JIRA issue for the type of functionality provided by EasyBind. If you don't want to use a 3rd party library, try Bindings.select:
Bindings.when(operation.isNotNull())
.then("null")
.otherwise(Bindings.select(operation, "name"));
Be aware the null checking in Bindings.select isn't super efficient. There's a JIRA issue for it.
Just in case if somebody using not Java itself but Kotlin.
It is a good idea to use wonderful tornadofx library.
There you can just use operation.select{it.name}. Although, this feature seems not to be documented yet, so it took some time to discover it.
Basically can an observer object's key be rename in JSViews?
This is related to stack question and my updated JSFiddle example,
in which I rename files where the file name is the object property as well as the key.
My real world example is actually using an onBeforeChange helper to perform the rename which is provided the arguments: oldValue & value.
Then I use the oldValue to navigate through the observer object to rename. But, because I don't rename the object key as well further renames will fail because the oldValue is now out of sync.
I hope that explanation plus the above fiddle makes sense... :s
Thanks for you consideration!
You can achieve something close to that by calling:
$.observable(object).setProperty("newKey", object.key);
$.observable(object).setProperty("key", undefined);
That will leave a property object.key with the value undefined, but will not actually remove the property.
If you want you can then call
delete object.key;
There will probably be a new $(object).removeProperty("someKey") in an upcoming update - which will allow you to write:
$.observable(object).setProperty("newKey", object.key);
$.observable(object).removeProperty("key");
UPDATE
You can now use removeProperty:
$.observable(object).removeProperty("key");
Should you be allowed to delete an item from the collection you are currently iterating in a foreach loop?
If so, what should be the correct behavior?
I can take quite a sophisticated Collection to support enumerators that track changes to the collection to keep position info correct. Even if it does some compromisation or assumptions need to be made. For that reason most libraries simply outlaw such a thing or mutter about unexpected behaviour in their docs.
Hence the safest approach is to loop. Collect references to things that need deleting and subsequently use the collected references to delete items from the original collection.
It really depends on the language. Some just hammer through an array and explode when you change that array. Some use arrays and don't explode. Some call iterators (which are wholly more robust) and carry on just fine.
Generally, modifying a collection in a foreach loop is a bad idea, because your intention is unknown to the program. Did you mean to loop through all items before the change, or do you want it to just go with the new configuration? What about the items that have already been looped through?
Instead, if you want to modify the collection, either make a predefined list of items to loop through, or use indexed looping.
Some collections such as hash tables and dictionaries have no notion of "position" and the order of iteration is generally not guaranteed. Therefore it would be quite difficult to allow deletion of items while iterating.
You have to understand the concept of the foreach first, and actually it depends on the programming language. But as a general answer you should avoid changing your collections inside foreach
Just use a standard for loop, iterate through the item collection backwards and you should have no problem deleting items as you go.
iterate in reverse direction and delete item one by one... That should proper solution.
No, you should not. The correct behaviour should be to signal that a potential concurrency problem has been encountered, however that is done in your language of choice (throw exception, return error code, raise() a signal).
If you modify a data structure while iterating over its elements, the iterator might no longer be valid, which means that you risk working on objects that are no longer part of the collection. If you want to filter elements based on some more complex notation, you could do something like this (in Java):
List<T> toFilter = ...;
List<T> shadow;
for ( T element : toFilter )
if ( keep(element) )
shadow.add(element);
/* If you'll work with toFilter in the same context as the filter */
toFilter = shadow;
/* Alternatively, if you want to modify toFilter in place, for instance if it's
* been given as a method parameter
*/
toFilter.clear();
toFilter.addAll(shadow);
The best way to remove an item from a collection you are iterating over it to use the iterator explitly. For example.
List<String> myList = ArrayList<String>();
Iterator<String> myIt = myList.iterator();
while (myIt.hasNext()) {
myIt.remove();
}