I have defined a property in Swift like:
var foo : String {
didSet {
doSomething()
}
}
So everytime I set foo like foo = "bar" my didSet will be executed.
However I can not find out on which thread didSet is being executed.
For example what happens in this case:
dispatch_async(some_queue, { () -> Void in
self.foo = "bar"
})
This will cause the didSet code to be executed. Will didSet be run on some_queue or always on the main_queue?
The property observers willSet and didSet are directly called from within the setter method, immediately
before/after the new value is stored, so all this executes on the same thread.
You can verify that by setting a breakpoint in didSet and inspecting
the stack backtrace, which would look like this:
* thread #2: tid = 0x4df3, 0x000000010024f9eb swtest2`swtest2.foo.didset : Swift.String(oldValue="foo") + 27 at main.swift:6, queue = 'myQueue', stop reason = breakpoint 1.1
* frame #0: 0x000000010024f9eb swtest2`swtest2.foo.didset : Swift.String(oldValue="foo") + 27 at main.swift:6
frame #1: 0x000000010024fb91 swtest2`swtest2.foo.setter : Swift.String(newValue="bar") + 177 at main.swift:4
frame #2: 0x000000010024fe3a swtest2`swtest2.(closure #1) + 42 at main.swift:13
...
Related
I am attempting to spin up a new thread in kotlin for android, using kotlin.concurrency.thread However I keep getting:
Unresolved reference: thread
I thought this was in the standard library?
Actual code:
fun identify(userId: Integer) {
thread() {
CustomExceptionHandler(context)
DoStuffClass.doStuff(context, userId)
}
}
The correct import statement is:
import kotlin.concurrent
The sample code should be:
fun identify(userId: Integer) {
thread {
CustomExceptionHandler(context)
DoStuffClass.doStuff(context, userId)
}
}
Because the thread function is defined as:
/**
* Creates a thread that runs the specified [block] of code.
*
* #param start if `true`, the thread is immediately started.
* #param isDaemon if `true`, the thread is created as a daemon thread. The Java Virtual Machine exits when
* the only threads running are all daemon threads.
* #param contextClassLoader the class loader to use for loading classes and resources in this thread.
* #param name the name of the thread.
* #param priority the priority of the thread.
*/
public fun thread(
start: Boolean = true,
isDaemon: Boolean = false,
contextClassLoader: ClassLoader? = null,
name: String? = null,
priority: Int = -1,
block: () -> Unit
): Thread {
...
}
As explained here, the thread function uses a lambda as the last parameter, then, by Kotlin syntax, a single parameter function didn't need the parenthesis, just the lambda block.
I wrote the following simple application:
object Main extends App {
var v: Int = 0
val t = new Thread(() => v = 1)
t.start()
t.join()
println(v) //prints 1
}
The thing that I was confused by was that we modify local variable from another thread... And that modification (made by the other thread) is visible in the main thread.
I thought local variables are always reside in a stack (stack memory the bottom is pointed to rsp register). I thought the stack memory is allocated for each thread in the application.
Upd: Even if we modify the app as follows it prints the same:
object Main {
def main(args: Array[String]) = {
var v: Int = 0
val t = new Thread(() => v = 1)
t.start()
t.join()
println(v) //prints 1
}
}
v is not a local variable in this case. It is a member of Main singletone object.
Update for the second example:
Closure () => v = 1 is compiled into an anonymous class that captures all variables it depends on. Stack-allocated primitives are turned into heap-allocated objects.
Here it is explained in details:
How does the memory management of closures in Scala work?
What this is doing is turning what appears to be a stack object into a heap object. In Java you can do this using array of 1 without adding special classes as Scala does.
public static void main(String... args) {
int[] v = { 0 };
Thread t = new Thread(() => v[0] = 1);
t.start();
t.join();
println(v[0]); //prints 1
}
First of all, I'm new in Kotlin, so please be nice :).
It's also my first time posting on StackOverflow
I want to literally STOP the current thread that I created but nothing works.
I tried quit(), quitSafely(), interrupt() but nothing works.
I created a class (Data.kt), in which I create and initialize a Handler and HandlerThread as follows :
class Dispatch(private val label: String = "main") {
var handler: Handler? = null
var handlerThread: HandlerThread? = null
init {
if (label == "main") {
handlerThread = null
handler = Handler(Looper.getMainLooper())
} else {
handlerThread = HandlerThread(label)
handlerThread!!.start()
handler = Handler(handlerThread!!.looper)
}
}
fun async(runnable: Runnable) = handler!!.post(runnable)
fun async(block: () -> (Unit)) = handler!!.post(block)
fun asyncAfter(milliseconds: Long, function: () -> (Unit)) {
handler!!.postDelayed(function, milliseconds)
}
fun asyncAfter(milliseconds: Long, runnable: Runnable) {
handler!!.postDelayed(runnable, milliseconds)
}
companion object {
val main = Dispatch()
private val global = Dispatch("global")
//fun global() = global
}
}
And now, in my DataManager, I use these to do asynchronous things :
fun getSomething(forceNetwork: Boolean ) {
val queue1 = Dispatch("thread1") // Create a thread called "thread1"
queue1.async {
for (i in 0..2_000_000) {
print("Hello World")
// Do everything i want in the current thread
}
// And on the main thread I call my callback
Dispatch.main.async {
//callback?.invoke(.........)
}
}
}
Now, in my MainActivity, I made 2 buttons :
One for running the function getSomething()
The other one is used for switching to another Controller View :
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
DataManager.getSomething(true)
}
val button2 = findViewById<Button>(R.id.button2)
button2.setOnClickListener {
val intent = Intent(this, Test::class.java) // Switch to my Test Controller
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
startActivity(intent)
finish()
}
Is there a way to stop the thread, because when I switch to my second View, print("Hello World") is still triggered, unfortunately.
Thanks for helping me guys I hope that you understand !
A thread needs to periodically check a (global) flag and when it becomes true then the thread will break out from the loop. Java threads cannot be safely stopped without its consent.
Refer to page 252 here http://www.rjspm.com/PDF/JavaTheCompleteReference.pdf that describes the true story behind the legend.
I think that a truly interruptible thread is only possible through the support of the operating system kernel. The actual true lock is held deep down by the CPU hardware microprocessor.
Hey i've been writing an application in which i need to create thread to perform background tasks while the GUI is being loaded. However no matter that i do i can find a way around this error:
error: invocation of void method not allowed as expression
Thread<void> thread = new Thread<void>.try("Conntections Thread.", devices_online(listmodel));
The line in question is the creating of a new thread which calls the "devices_online" method.
The Full code which is being effected is:
try {
Thread<void> thread = new Thread<void>.try("Conntections Thread.", devices_online(listmodel));
}catch(Error thread_error){
//console print thread error message
stdout.printf("%s", thread_error.message);
}
And Method is:
private void devices_online(Gtk.ListStore listmodel){
//clear the listview
listmodel.clear();
//list of devices returned after connection check
string[] devices = list_devices();
//loop through the devices getting the data and adding the device
//to the listview GUI
foreach (var device in devices) {
string name = get_data("name", device);
string ping = get_data("ping", device);
listmodel.append (out iter);
listmodel.set (iter, 0, name, 1, device, 2, ping);
}
}
Ive done so much Googleing but Vala isn't exactly the most popular language. Any help?
Like the compiler error says, you are getting a void by calling a method. Then you are trying to pass the void value into the thread constructor.
Thread<void> thread = new Thread<void>
.try ("Conntections Thread.", devices_online (listmodel));
The second cunstructor argument of Thread<T>.try () expects a delagate of type ThreadFunc<T> which you are not satisfying.
You are confusing a method call with a method delegate.
You can pass an anonymous function to fix that:
Thread<void> thread = new Thread<void>
.try ("Conntections Thread.", () => { devices_online (listmodel); });
I want to implement something like the producer-consumer problem (with only one information transmitted at a time), but I want the producer to wait for someone to take his message before leaving.
Here is an example that doesn't block the producer but works otherwise.
class Channel[T]
{
private var _msg : Option[T] = None
def put(msg : T) : Unit =
{
this.synchronized
{
waitFor(_msg == None)
_msg = Some(msg)
notifyAll
}
}
def get() : T =
{
this.synchronized
{
waitFor(_msg != None)
val ret = _msg.get
_msg = None
notifyAll
return ret
}
}
private def waitFor(b : => Boolean) =
while(!b) wait
}
How can I changed it so the producers gets blocked (as the consumer is) ?
I tried to add another waitFor at the end of but sometimes my producer doesn't get released.
For instance, if I have put ; get || get ; put, most of the time it works, but sometimes, the first put is not terminated and the left thread never even runs the get method (I print something once the put call is terminated, and in this case, it never gets printed).
This is why you should use a standard class, SynchronousQueue in this case.
If you really want to work through your problematic code, start by giving us a failing test case or a stack trace from when the put is blocking.
You can do this by means of a BlockingQueue descendant whose producer put () method creates a semaphore/event object that is queued up with the passed message and then the producer thread waits on it.
The consumer get() method extracts a message from the queue and signals its semaphore, so allowing its original producer to run on.
This allows a 'synchronous queue' with actual queueing functionality, should that be what you want?
I came up with something that appears to be working.
class Channel[T]
{
class Transfer[A]
{
protected var _msg : Option[A] = None
def msg_=(a : A) = _msg = Some(a)
def msg : A =
{
// Reading the message destroys it
val ret = _msg.get
_msg = None
return ret
}
def isEmpty = _msg == None
def notEmpty = !isEmpty
}
object Transfer {
def apply[A](msg : A) : Transfer[A] =
{
var t = new Transfer[A]()
t.msg = msg
return t
}
}
// Hacky but Transfer has to be invariant
object Idle extends Transfer[T]
protected var offer : Transfer[T] = Idle
protected var request : Transfer[T] = Idle
def put(msg : T) : Unit =
{
this.synchronized
{
// push an offer as soon as possible
waitFor(offer == Idle)
offer = Transfer(msg)
// request the transfer
requestTransfer
// wait for the transfer to go (ie the msg to be absorbed)
waitFor(offer isEmpty)
// delete the completed offer
offer = Idle
notifyAll
}
}
def get() : T =
{
this.synchronized
{
// push a request as soon as possible
waitFor(request == Idle)
request = new Transfer()
// request the transfer
requestTransfer
// wait for the transfer to go (ie the msg to be delivered)
waitFor(request notEmpty)
val ret = request.msg
// delete the completed request
request = Idle
notifyAll
return ret
}
}
protected def requestTransfer()
{
this.synchronized
{
if(offer != Idle && request != Idle)
{
request.msg = offer.msg
notifyAll
}
}
}
protected def waitFor(b : => Boolean) =
while(!b) wait
}
It has the advantage of respecting symmetry between producer and consumer but it is a bit longer than what I had before.
Thanks for your help.
Edit : It is better but still not safeā¦