 Oh, yes. Thank you. Okay. This is the right spot. Okay. Good. So, here is the outline of my talk. So, my implementation, my application is mathematical, but I will almost entirely try to focus on the data part. So, the problem is that you have algorithms that, I can probably try to fix this. It's okay? It's okay. So, I mean, I think the slides will be a little bit better afterwards. If you think about an algorithm, what is an algorithm it has to terminate. But some algorithms they actually, they will never terminate like here in the example. If you want to compute the expansion of a transcendental number like pi, it will never ever finish because pi doesn't have a finite number of bits, doesn't have a finite number of decimal places. So, this loop here goes to infinity. Nevertheless, every result here, as you keep it running a little bit longer, it will give you a little bit more precision. Now, when do you stop? Sometimes, I mean, this is a toy example and I will not refer to it later. But in a lot of applications where you approximate anything, something you don't really know what is a good result. So, you want to, as a user, decide when to stop. Actually, this is all about controlling loops that go on forever, and a loop that goes on forever, the immediate reflex that you have is control C. That's also what we are going to interrupt over here. It could be that you have a program running for six months and then the user hits control C. Then you want your program to say, really, really, you really want to stop me, and then indeed the user can confirm. But perhaps control C should not be used. So, control C as a data programmer, you can actually control. Actually, the goal of this talk here is that I will give you in a couple of slides. So, there will be a data code on the slides, and you can do this with actually very simple routines. So, here is the session. Here is the test. We have a counter that goes on to infinity. So, there is a counter here, and the user each time can hit control C. For one reason or another, I can actually never get it right after one. I'm not fast enough, but you can tune that as well. So, the feedback here is just that it reports how much time it has spent. But you can give all kinds of feedback, depending on the result, and then the user can confirm the abort or can actually let the continuation go on. So, the program by default wants to continue. So, in Ada, you can attach a handler to the interrupt. You have to compile it with unreserved all interrupts, somewhere preferably in your main program, you have that program there, and then actually you can redefine or you can define a handler for this control C. So, there is a global state. So, the global state here in the example is just the value of the counter. Then you have to define what your handler is. The handler here will be extremely simple. Then you have the actual computation, which is the code for the loop, and then you have a main test procedure. Actually, that's the name of the main test procedure over there, the SIG and handler test. And if you run gnotmake on it, and you have the other files that are then compiled, and finally you have then the final executable, the tests. So, four files are defining this example here, although you could have put everything on one file. A good practice of object-oriented programming is always that you plan for extension. So, I put everything that was logically different in different files. Four files, here is the simplest one. This is just storing the global state. So, this is probably overkill, one package for one constant, but in the application where I'm looking for, this will store the job queue. So, this will be the interface to the job queue. This will be everything that you want to compute. Here we just count. So, we have a value that we want to store. So, this is meant for extension. Then we have the handler, the specification of the handler. The handler will be defined in this procedure handle, and that will do something very, very simple, just adding the count, adding one to the count, and then actually with the adding of the count, you have the weight that is enabled. So, for the compiler, you have to tell that the handle is actually the handler that you have for your interrupt, and the name of the sig int for the control C is defined in this package here. And there's also another counter. You have the counter that counts how many times the interrupt has been occurring. So, this is the specification. Then the implementation is just doing plus one, and sometimes we do minus one as well. So, we do plus one each time the handler is called, it is the plus one, and then actually the method weight will actually be accepted. What this actually means that is if the, so the call count was initialized to zero. So, the initialization to zero means that actually the weight is not accepted. And this is then also what the handler does, it waits. So, if that, so what the handler actually does, it actually releases the weight. That's it. And you can use this for then the quote that will handle the interrupt. The quote that handles the interrupt is actually then released at that point. So, that's then the next task. So, this handler actually doesn't know anything about computing pie or about doing anything. So, this is completely separate. You can use this for anything that you want to compute. Here is the computer or the worker or whatever does the processing. This is the package, the counting here. I mean, this is the package that will do the next job. There is an interactive routine that will be called when the interrupt occurs. And this is better defined here because you want to have this application dependent. And then you have the task counter, where the stop happens. And there is the global state. The global state is whether we continue or not, whether the counter continues or not. The body doesn't fit on one slide. So, this is very much straightforward here. This is where the question happens to the user, do you want to continue or not? And that actually will return the Boolean that will be assigned to the state. So, that Boolean that is returned here is assigned to the state continue, which is on initialization too. And here comes then the most difficult piece of the code. This is the, so I mentioned the reaction time. If you want to cheat a little bit and you want really to stop your counter after one, you put 0.5 to one. We have the stop method. What the stop method will do, and the stop method gets released when the handler releases its weight, it will actually first prompt the user whether you want to continue counting or not. If that is the case, then actually you have to reschedule the handler. So, the handler, you have to be re-queued. So, the re-queue is a keyword in Ada. So, you have to make sure that as the continuation as the counting continues, that you can still interrupt future runs. Otherwise, if the user said, I don't want to continue, you actually exit. So, you exit when not continue. The global counter is the value was stored in that package global counter. So, the counter will actually increment the value here. So, instead of incrementing that global value counter, this is where all the computation work happens, essentially. And then we are at the main procedure. So, the main program where you put your unreserved all interrupts. So, that actually tells the compiler, hey, I want to redefine that interrupt. We have a task that will handle the signal. And then there is here the main body. So, that will just actually launch that handler. Then comes the main program that puts everything together. So, we had the handler, the very simple handler that actually had to wait method in there and then the handle. So, when the handler gets executed, the counter gets incremented and then the wait gets accepted. And then actually you enter this loop here. So, you then can print the execution time and then you have the stop that gets called in the counter. That method then that gets accepted. You leave the main loop when the final state of the counter becomes false. And that's actually it. So, that's the main program that will run the test. Now, where is this being used? So, this is my last slide. So, you want to have this running in a computation that is kind of unpredictable. So, sometimes you run a program and it returns immediately, but sometimes it doesn't. So, there are something... And then actually you want to know what is the system thinking? What is the program doing? Then actually you can do the control C and then actually you can give an update on the status. So, I work on polynomial system solving and sometimes you can very quickly find the real root but sometimes the real root is very sparse among a huge list of complex roots. And sometimes it's unpredictable where that is. So, I think that an application in general and mathematical sense could be in searching. If you search for the result, on average you will get it quite quick but there may be cases where you don't get it right away. And then a control C can be interesting to see the complexity. So, the code is available on GitHub. So, I mentioned the URL in the beginning that also points to this PHC-PAC source code there. It can be found in that tasking directory. So, there are four scripts here. I mean four files and these files are also available in that source code directory. So, what I decided to present now was just what you needed to know to get started to build a controlling mechanism to implement your own control C. Thank you for your attention. If there's a question, can I ask you another question? So, the order delay that you used in your set, what does it feel like? Oh, the order delay is just actually, yes, very good question. So, it actually simply waits for half a second. So, this is not really computing here. So, in the interest of computation, you would put that over here. It should time out. So, it's part of the synthesis of accept statement, essentially. It means if it's not accepted within the zero point frame, second, you give up and continue. Yeah, it's a bit confusing, indentation as well. It's really part of accept statement. Select. Yeah, it's part of the select. Yeah, so the OR. Perhaps it could have usually been after accept. The select has two arms and usually you put the delay zero five. Yeah, it's essentially, I mean, logically, it's the last accept statement, logic of it has. What? Yeah, that's what I mean. So, it's not going to do right. Regarding the problem you used to unwind the signal handler, does that do it for all signal handlers and you have to implement all? Yeah, so it's actually a very good mechanism, because it allows you to target one particular exception. So, you have here, and you can write as many handlers that you need for every different. Yes, you can still, yeah, when I was testing this, I was very happy that I could do the odd, the alternatives. So, the control C I could no longer use, but the other ones I could still use. Okay, thank you again. Sure, I can still answer the question. I might be missing something. Why do you need to read? Oh, because the handler, so the handler actually does not have a loop. The handler is very simple. So, it's extremely big. So, the other question that you could have asked, what happens if you do control C, control C, control C. So, you have a user who will not read whatever comes on the message. This is then, you have to capture then over here in the continue. So, if the user does not read it, you probably need to have a handler also here. So, but you lose the control C, but yeah. That's control C, does that stop? No, yeah, yeah. So, the control C actually makes sure that the wait stops. So, no longer waits. And then actually the method stop gets accepted here. And then you have to continue counting.