How can I replace the below busy waiting with condition variables?
while (this_thread != pthread_self()){
pthread_mutex_lock(&lock);
if(this_thread == -1)
this_thread = get_id();
pthread_mutex_unlock(&lock);
}
Thanks!
Assuming the value returned by get_id() is only set via a function called set_id(), please see this pseudo code:
globals
Mutex mutex
Condition cond
Id id
code
set_id(id_in)
{
mutex_lock
id = id_in
cond_signal
mutex_unlock
}
test()
{
mutex_lock
while ((this_thread = get_id()) != pthread_self())
cond_wait
mutex_unlock
}
Related
I would like to count the attempts entering the PIN and show notifications accordingly:
val remainingPinCounter = remember { mutableStateOf(3) }
//
if(pinState == WRONG_PIN) {
remainingPinCounter.value--
showWrongPinNotification(remainingPinCounter)
}
#Composable
private fun showWrongPinNotification(retries: MutableStateOf<Int>){
if(retries.value > 0) Log.d("TAG", "Remaining Retries := $retries.value)
else Log.d("TAG", "All $retries.value attempts failed!)
//..
}
But the showWrongPinNotification() is called continously with increasing remainingPinCounter to -infinity , although I decrement it via pinState == WRONG_PIN only?! I guess the state WRONG_PIN is not changing and thus constantly calling showWrongPinNotification with decremented values?
It worked properly without remeber ->val remainingPinCounter = 3
if(pinState == WRONG_PIN) {
remainingPinCounter.value--
showWrongPinNotification(remainingPinCounter)
}
might be the infinite recompositions if you don't change pinState before next recomposition. If that's the case on each recomposition conditional block is invoked and value of remainingPinCounter changed constantly.
LaunchedEffect(pinState) {
if(pinState == WRONG_PIN) {
remainingPinCounter.value--
showWrongPinNotification(remainingPinCounter)
}
}
Other option is to decrease it only once using LaunchedEffect as
is it safe to create a task with a variable?
TaskHandle_t blablaTaskHandle= NULL;
...
bool startTask = readAVariable();
if(startTask ){
xTaskCreate(&blabla, "blabla", 2048, NULL, 2, &blablaTaskHandle);
}
And also suspend it and resume:
// this is in the main loop
bool suspendTask = true;
if( suspendTask && (blablaTaskHandle!= NULL)){
vTaskSuspend(blablaTaskHandle);
}
else{
vTaskResume(blablaTaskHandle);
}
You create a task with a function call, not a variable, so I'm not sure what you are asking. From the API documentation, and the hundreds of provided examples, it looks like your use of the first parameter to xTaskCreate() is probably wrong.
how to use liveData coroutine block
in offical doc
https://developer.android.google.cn/topic/libraries/architecture/coroutines#livedata
now can use livedata with coroutine in liveData block
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
when i try to use like this
fun onLogin(v: View) {
liveData(context = Dispatchers.IO) {
val reqLogin = ReqLogin(account = account.value?:"", password = MD5(password.value?:""))
val data = HttpManager.service(MobileApi::class.java).loginSuspend(reqLogin)
emit(data.data!!)
}
}
codes in block not executed
search and found that liveData block always use for assignment
https://medium.com/androiddevelopers/viewmodels-and-livedata-patterns-antipatterns-21efaef74a54
if want to refresh the livedata value, can use Transformations like
LiveData<Repo> repo = Transformations.switchMap(repoIdLiveData, repoId -> {
if (repoId.isEmpty()) {
return AbsentLiveData.create();
}
return repository.loadRepo(repoId);
});
but how can i use it when
1. activity onResume and refresh the data from server
2. some click event trigger the request and get some new data to show
in my login scenes, use viewModelScope seems more useful
fun onLogin(v: View) {
val reqLogin = ReqLogin(account = account.value ?: "", password = MD5(password.value ?: ""))
viewModelScope.launch {
val data = withContext(Dispatchers.IO) {
HttpManager.service(MobileApi::class.java).loginSuspend(reqLogin)
}
_userInfo.value = data.data!!
_isLogin.value = true
}
}
fun onLogin(v: View) {
liveData(context = Dispatchers.IO) {
val reqLogin = ReqLogin(account = account.value?:"", password = MD5(password.value?:""))
val data = HttpManager.service(MobileApi::class.java).loginSuspend(reqLogin)
emit(data.data!!)
}
}
Code block is not executed because the documentation says that
The code block starts executing when LiveData becomes active and is
automatically canceled after a configurable timeout when the LiveData
becomes inactive.
You should make it active by observing it.
I want to validate input corresponding to the following grammar snippet:
Declaration:
name = ID "=" brCon=BracketContent
;
BracketContent:
decCon=DecContent (comp+=COMPARATOR content+=DecContent)*
;
DecContent:
(neg=("!"|"not"))? singleContent=VarContent (op+=OPERATOR nextCon+=VarContent)*
;
My validation looks like that:
#Check
def checkNoCycleInHierarchy(Declaration dec) {
if(dec.decCon.singleContent.reference == null) {
return
}
var names = newArrayList
var con = dec.decCon.singleContent
while(con.reference != null) {
con = getThatReference(con).singleContent
if(names.contains(getParentName(con))) {
val errorMsg = "Cycle in hierarchy!"
error(errorMsg,
SQFPackage.eINSTANCE.bracketContent_DecCon,
CYCLE_IN_HIERARCHY)
return
}
names.add(getParentName(con))
}
}
But when I test this validation with a testCaseit returns me an error message:
Expected ERROR 'raven.sqf.CycleInHierarchy' on Declaration at [-1:-1] but got
ERROR (org.eclipse.emf.ecore.impl.EClassImpl#5a7fe64f (name: Declaration) (instanceClassName: null) (abstract: false, interface: false).0) 'Error executing EValidator', offset null, length null
ERROR (org.eclipse.emf.ecore.impl.EClassImpl#5a7fe64f (name: Declaration) (instanceClassName: null) (abstract: false, interface: false).0) 'Error executing EValidator', offset null, length null
I just can't figure out what's wrong with it so I hope that someone of you might have an idea.
Greetings Krzmbrzl
You test utility tells you that the validator did not produce the expected validation error ("CycleInHierarchy").
Instead, the validator produced the error "Error executing EValidator".
Which means an exception has been thrown when your validator was executed.
It turned out it was an internal error...I'm still not exactly sure what went wrong but I have rewritten my validation method and now it works as expected.
Now the method looks like this:
enter code here#Check
def checkNoCycleInHierarchy(Declaration dec) {
if(dec.varContent.reference == null) {
//proceed only if there is a reference
return
}
var content = dec.varContent
var names = newArrayList
while(content.reference != null && !names.contains(getParentName(content))) {
names.add(getParentName(content))
content = content.reference.varContent
if(names.contains(getParentName(content))) {
val errorMsg = "Cycle in hierarchy!"
error(errorMsg,
SQFPackage.eINSTANCE.declaration_BrCon,
CYCLE_IN_HIERARCHY)
return
}
}
}
I have the suspicion that there was a problem with the usage of my "getThatReference" in this case.
Greeting Krzmbrzl
I have code like this:
-(IBAction)send {
if ([self isCorrect1] && [self isCorrect2] && ...) {
[self sendRequest];
}
}
-(BOOL)isCorrect1 {
...
}
-(BOOL)isCorrect2 {
...
}
Every isCorrect method is checking some condition showing some message in the view and returning result of the checking. I noticed that if first condition is false it will only show error message for the first method (and I need all of them to be checked) and no breakpoint is triggered inside these methods. I thought it was some kind of LLVM optimization so I created code like this:
-(IBAction)send {
BOOL correct = [self isCorrect1];
correct = correct && [self isCorrect2];
...
if (correct) {
[self sendRequest];
}
}
And is still not working correctly. Do I have to create new BOOL variable to store result for the check or is there some other way?
Since the first condition is evaluated to false, it won't check for the rest of the conditions and will go to the else part straightaway.
Try this.
BOOL finalResult = [self isCorrect1];
finalResult = [self isCorrect2] && finalResult;
finalResult = [self isCorrect3] && finalResult;
finalResult = [self isCorrect4] && finalResult;
...
if (finalResult) {
}
This will go through all of the isCorrect tests and will let you know if it passed all of them in the end or not.
The behaviour you see is the expected behaviour of the &&, namely, it "short-circuits" the evaluation, if it can determine the result in advance, before having evaluated all conditions:
expression-yielding-false && something-else
The result of the above is completely determined by the first part; regardless of what the second operand yields, the final result is false. This allows you to write something like:
if (obj != null && obj->count == 3)
{
...
}
If the && did not have the short-circuit behaviour, you'd have to write
if (obj != null)
{
if (obj->count == 3)
{
...
}
}
The || has a similar behaviour. In case of
something-yielding-true || anything
the right-hand side cannot affect the result value, as the left-hand side already returned true.
One possible work-around would be:
int succeeses = 0;
succeesses += [self isCorrect1]? 1 : 0;
succeesses += [self isCorrect2]? 1 : 0;
succeesses += [self isCorrect3]? 1 : 0;
if (successes == 3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
If you need to know, which tests passed, and which failed, you can try:
BOOL passed1 = [self isCorrect1];
BOOL passed2 = [self isCorrect2];
BOOL passed3 = [self isCorrect3];
if (passed1 && passed2 && passed3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
A more dense version of the above would be
int passed = 0;
passed |= [self isCorrect1]? (1 << 0) : 0;
passed |= [self isCorrect2]? (1 << 1) : 0;
passed |= [self isCorrect3]? (1 << 2) : 0;
if (passed == 7)
{
// All tests did succeed
}
else
{
if (passed & (1 << 0))
{
// First test passed
}
else
{
// First test failed
}
if (passed & (1 << 1))
{
// Second test passed
}
else
{
// Second test failed
}
if (passed & (1 << 2))
{
// Third test passed
}
else
{
// Third test failed
}
}
which is simply a more occult formulation of the version with a boolean variable per test tried.