How to know how many tasks are already completed? - delphi

In C++ Builder 10.3.3 I'm using the following test code:
int count = 500;
_di_ITask* task = new _di_ITask[count];
ProgressBar1->Position = 0;
for(int i = 0; i < count; i++){
task[i] = TTask::Create([i, this](){
// do something...
Sleep(10);
});
task[i]->Start();
//ProgressBar1->Position = numberOfFinishedTasks;
//Application->ProcessMessages();
}
TTask::WaitForAll(task, count - 1);
In this case there are 500 test tasks and I would like my ProgressBar component to show the current number of completed tasks. I don't know how to get that info. Thanks!

The simplest solution is to have the lambda itself update the ProgressBar before exiting. You can use TThread::Synchronize() or TThread::Queue() for that.
The problem is, TTask::WaitForAll() is a blocking method that does not pump the main UI message queue at all, so Synchronize()/Queue() requests will not be processed at all. You can get around that by calling WaitForAll() in a loop with a timeout so that the loop can pump messages as needed.
Try something like this:
int count = 500;
std::vector<_di_ITask> task(count);
ProgressBar1->Position = 0;
ProgressBar1->Min = 0;
ProgressBar1->Max = count;
ProgressBar1->Step = 1;
for(int i = 0; i < count; ++i){
task[i] = TTask::Create(
[i, this](){
// do something...
TThread::Queue(nullptr, ProgressBar1->StepIt);
}
);
task[i]->Start();
}
while (!TTask::WaitForAll(task.data(), count - 1, 1000)){
Application->ProcessMessages();
}

Related

When is a MIDINoteMessage played in a MusicTrack? iOS

I'm creating a MusicTrack of MIDI Notes that are successfully played using
MusicPlayerStart(sequencePlayer)
But I would like to know when are they played, so I can update the UI for each MIDI Note played.
// Creating MIDI Track
MusicTrack track;
UInt32 trackIndex = 0;
musicTrackAtIndex(trackIndex, &track);
//Adding Tempo
addTempoEvent(0.0, 120);
// Adding MIDI notes
const int channel = 0;
MIDINoteMessage note;
note.channel = channel;
note.velocity = 100.0;
note.duration = 0.3;
note.releaseVelocity = 0;
note.note = 68;
addMIDINoteToTrack(track, note, 1);
note.note = 78;
addMIDINoteToTrack(track, note, 2);
note.note = 88;
addMIDINoteToTrack(track, note, 3);
note.note = 98;
addMIDINoteToTrack(track, note, 4);
MusicTimeStamp trackEnd = 4;
addEndOfTrackAtTime(trackEnd);
setLoopTrack(true);
playSequence();
EDIT
Showing in more detail how I'm building the MIDI Track.
-(void) playing4NotesInLoop {
MusicTrack musicTrack;
MusicSequence musicSequence;
MusicPlayer musicPlayer;
const int loop_length = 4;
NewMusicSequence(&musicSequence);
// Create a client
MIDIClientRef virtualMidi;
MIDIClientCreate(CFSTR("Virtual Client"),
MyMIDINotifyProc,
NULL,
&virtualMidi);
// Create an endpoint
MIDIEndpointRef virtualEndpoint;
MIDIDestinationCreate(virtualMidi, #"Virtual Destination", MyMIDIReadProc, self.samplerUnit, &virtualEndpoint);
MusicSequenceNewTrack(musicSequence, &musicTrack);
MIDINoteMessage aMessage;
aMessage.channel = 1;
aMessage.duration = 0.5f;
aMessage.velocity = 100;
for(int i=0; i<4; ++i)
{
if (i==0) {
aMessage.note = 30;
}else {
aMessage.note = 60;
}
MusicTrackNewMIDINoteEvent(musicTrack, i, &aMessage);
}
MusicTrackLoopInfo loop_info;
loop_info.loopDuration = loop_length;
loop_info.numberOfLoops = 0;
MusicTrackSetProperty(musicTrack, kSequenceTrackProperty_LoopInfo, &loop_info, sizeof(MusicTrackLoopInfo));
MusicTimeStamp track_length;
track_length = loop_length;
MusicTrackSetProperty(musicTrack, kSequenceTrackProperty_TrackLength, &track_length, sizeof(MusicTimeStamp));
MusicSequenceSetMIDIEndpoint(musicSequence, virtualEndpoint);
NewMusicPlayer(&musicPlayer);
MusicPlayerSetSequence(musicPlayer, musicSequence);
MusicPlayerStart(musicPlayer);
}
With this code I'm successfully playing a loop of 4 notes, a MusicSequenceSetMIDIEndpoint(musicSequence, virtualEndpoint) has been set up specifying the read proc. I used the same code but loading a MIDI file and the read proc it's successfully called for each note.
You create a virtual endpoint with MIDIDestinationCreate and then call MusicSequenceSetMIDIEndpoint to connect your sequence to it. The read proc that you specify will be called on each event.

STM32L-Discovery error message?

I'm trying to program a stm32l-discovery board and have come across this error that keeps appearing when I try to build my project.
error: #29: expected an expression
for (int i = 0; i <999; i++){
I'm using Keil uVision 4.
Source:
while (1) {
////fade up
int i = 0;
for (int i = 0; i <999; i++) {
TIM_SetCompare2(TIM2,i);
////Pulse width is set with this function
delay(100);
//// the '2' relates to the channel in use
}
}
Anyone know what this means?

AudioBufferList Increase in Memory Usage

I have the following code in a loop (it gets called every 1/4 second).
(I have removed the rest of the code to narrow the problem down to the following).
dispatch_async(self.audioQueue, ^{
AudioBufferList *aacBufferList;
aacBufferList = malloc(sizeof(AudioBufferList));
aacBufferList->mNumberBuffers = 1;
aacBufferList->mBuffers[0].mNumberChannels = aacStreamFormat.mChannelsPerFrame;
aacBufferList->mBuffers[0].mDataByteSize = maxOutputPacketSize;
aacBufferList->mBuffers[0].mData = (void *)(calloc(maxOutputPacketSize, 1));
// Other code was here. As stated above, I have removed it to isolate the problem to the allocating and freeing of memory for the AudioBufferList
freeABL(aacBufferList);
}
And the freeABL function:
void freeABL(AudioBufferList *abl)
{
for (int i = 0; i < abl->mNumberBuffers; i++)
{
free(abl->mBuffers[i].mData);
abl->mBuffers[i].mData = NULL;
}
free(abl);
abl = NULL;
}
The problem I have, is every time this loops the memory consumption of my app increased, until I receive a memory warning.

Xlib Muti-thread program only works under strace

I'm writing a muti-thread program using xlib, pthread and cairo.
This program create a thread in order to draw ten points after a click event.
The problem is:
After the program drew three points, it got crashed and xlib complaint
X Error of failed request: BadRequest (invalid request code or no such operation)
Major opcode of failed request: 0 ()
Serial number of failed request: 67
Current serial number in output stream: 97
However, it can work properly when I'm using strace like "strace ./a.out".
Here's my code-clips:
void *draw_point(void *arg) { //paint random-postion point
int i = 0;
int seed;
double x ,y;
srand(seed);
cairo_set_source_rgba (cairo, 1, 0.2, 0.2, 0.6);
for(i = 0; i< 10; i++) {
x = rand() % 200;
y = rand() % 200;
if(candraw) {
cairo_arc (cairo, x, y, 10.0, 0, 2*M_PI);
cairo_fill (cairo);
}
hasdraw = true;
sleep(1);
}
return NULL;
}
bool win_main(void)
{
int clickx = 0, clicky = 0;
unsigned long valuemask;
XEvent event;
valuemask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask;
XSelectInput(display, win, valuemask);
pthread_t thread;
while (1) {
while (XPending(display) == 0) {
candraw = true;
if(hasdraw)
XFlush(display);
candraw = false;
}
XNextEvent(display, &event);
candraw = false;
switch (event.type) {
case MotionNotify:
//...
break;
case ButtonPress:
clickx = event.xbutton.x;
clicky = event.xbutton.y;
if(clicky < 50)
pthread_create(&thread, NULL, draw_point, NULL);
break;
case ButtonRelease:
//...
break;
default:
break;
}
}
return 0;
}
Does anyone has an idea about this weird problem?
Thanks a lot!
The problem is caused by using multi-threading with the 2 threads trying to access the display at the same.
strace will change the timing, so the threads are accessing the display at different times.
Xlib does have functions to prevent conflict. Lookup XInitThreads, which enables thread support and XLockDisplay and XUnlockDisplay, which you will need to call from each thread before and after accessing the display.

Problem with wsarecv while using with IOCP

I am new to IOCP and struggling with this for last few weeks.
I have pasted some core part of my code below related to IOCP.This may not be executed perfectly as I clipped some part to make it easy to understand.
I am struggling while receiving the data.As it comes to wsarecv in worket thread, wsarecv returns WSA_IO_PENDING error code so I call WSAGetOverlappedResult to check operation to be completed.
Twist comes here, rather it proceed and call my local function ProcessTelegramData after WSAGetOverlappedResult , same part of code(wsarecv called again) is executed again by another worker thread which try to call ProcessTelegramData and buffer value is invalid in it.
I am unable to understand
why another thread calling wsarecv again when WSAGetOverlappedResult is called and
why buffer value is getting invalidated?
unsigned LicTCPServer::WorkerThread(LPVOID lpParam)
{
//int nThreadNo = (int)lpParam;
LicTCPServer* pThis = reinterpret_cast<LicTCPServer*>(lpParam);
void *lpContext = NULL;
OVERLAPPED *pOverlapped = NULL;
CClientContext *pClientContext = NULL;
DWORD dwBytesTransfered = 0;
int nBytesRecv = 0;
int nBytesSent = 0;
DWORD dwBytes = 0, dwFlags = 0;
//Worker thread will be around to process requests, until a Shutdown event is not Signaled.
while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
{
BOOL bReturn = GetQueuedCompletionStatus(
g_hIOCompletionPort,
&dwBytesTransfered,
(LPDWORD)&lpContext,
&pOverlapped,
INFINITE);
if (NULL == lpContext)
{
//We are shutting down
break;
}
//Get the client context
pClientContext = (CClientContext *)lpContext;
if ((FALSE == bReturn) /*|| ((TRUE == bReturn) && (0 == dwBytesTransfered))*/)
{
//Client connection gone, remove it.
pThis->RemoveFromClientListAndFreeMemory(pClientContext);
continue;
}
WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();
//printf("reached %d\n",pClientContext->GetOpCode());
printf("Get Queued received\n");
switch (pClientContext->GetOpCode())
{
case OP_READ:
{
//Once the data is successfully received, we will print it.
//pClientContext->SetOpCode(OP_WRITE);
pClientContext->ResetWSABUF();
dwFlags = 0;
//int a = recv(pClientContext->GetSocket(), p_wbuf->buf, p_wbuf->len, 0);
//Get the data.
if(WSARecv(pClientContext->GetSocket(), p_wbuf, 1, &dwBytes, &dwFlags, p_ol, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("Error occured at WSARecv()\n");
return 0;
}
}
DWORD byteTr = 0;
WSAGetOverlappedResult(pClientContext->GetSocket(),p_ol,&byteTr,TRUE,&dwFlags);
if( byteTr > 0 )
{
//doing some operatin on data received
printf("Process tele called\n");
g_pLicServFunc->ProcessTelegramData(pClientContext->GetSocket(), p_wbuf->buf, byteTr);
}
if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
}
break;
case OP_WRITE:
char szBuffer[MAX_BUFFER_LEN];
//Send the message back to the client.
pClientContext->SetOpCode(OP_READ);
pClientContext->SetTotalBytes(dwBytesTransfered);
pClientContext->SetSentBytes(0);
//p_wbuf->len = dwBytesTransfered;
dwFlags = 0;
DWORD temp;
//Overlapped send
printf("reached Going to send\n");
//send(pClientContext->GetSocket(), p_wbuf->buf,p_wbuf->len, 0);
nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
&temp, dwFlags, p_ol, NULL);
if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
break;
default:
printf("reached to default\n");
//We should never be reaching here, under normal circumstances.
break;
} // switch
} // while
return 0;
}
I had a similar issue with WSARecv where it always queued to the io completion queue, even if it succeeded immediately. I had to ignore a return value indicating success and instead handle the queued result that I got from GetQueuedCompletionStatus.

Resources