-1

I'm having the following code (C++ Builder 10.3.3):

bool isPrime(int n){
    if (n <= 1)
        return false;
    for(int i = 2; i < n/2; i++)
        if(!(n%i))
            return false;
    return true;
}

void __fastcall TForm1::Button3Click(TObject *Sender)
{
    auto start_t = high_resolution_clock::now();
    _di_ITask task[50000];
    int count = 50000;
    // _di_ITask* task = new _di_ITask[count]; // compiles, but gives incorrect end result

    vector<int> prim;
    for(int i = 0; i < count; i++){
        task[i] = TTask::Create([i, this, &prim](){
        if(isPrime(i)){
            EnterCriticalSection(&cs);
            prim.push_back(i);
            LeaveCriticalSection(&cs);
            };
        });
        task[i]->Start();
    }
    TTask::WaitForAll(task,(sizeof(task)/sizeof(task[0])-1));
    auto end_t = high_resolution_clock::now();
    auto duration = duration_cast<milliseconds>(end_t - start_t).count();
    ShowMessage("Prime count: " + String(prim.size()) + " Time: " + IntToStr(duration) + " ms.");
}

When running this code I always get 5134. But, I want to set the number of tasks (_di_ITask objects) dynamically and not to have it fixed. So, instead

_di_ITask task[50000];

i want to have something like this:

int count = 50000;
_di_ITask* task = new _di_ITask[count]();

This compiles, but at the end I always get incorrect (random) result. What am I doing wrong?

Tracer
  • 2,544
  • 2
  • 23
  • 58
  • Does this answer your question? [How to find the 'sizeof' (a pointer pointing to an array)?](https://stackoverflow.com/questions/492384/how-to-find-the-sizeof-a-pointer-pointing-to-an-array) – 273K Dec 02 '19 at 15:18
  • @S.M. It does not return false for "2". But yes, sizeof is probably the issue here.. – Tracer Dec 02 '19 at 15:34
  • Using "naked" new is not a good idea especially for arrays. Use std::vector if you need dynamic array and std::array if you need static one. It is not easy to answer your question, there are some missing parts of the code. Don't forget to delete _di_ITask, you can even reset it, not mandatory but good practice. – Jules Dec 02 '19 at 15:42
  • @Jules "*Don't forget to delete _di_ITask*" - that is not necessary. `_di_...` types are aliases for the `DelphiInterface` class, a smart pointer to a reference-counted object, similar to `std::shared_ptr` but using Delphi-style interfaces derived from `IInterface`, which is Delphi's equivalent to COM's `IUnknown` – Remy Lebeau Dec 02 '19 at 16:21

1 Answers1

0

I got it. Instead

TTask::WaitForAll(task,(sizeof(task) / sizeof(task[0]) - 1));

I need to use

TTask::WaitForAll(task, (sizeof(task[0]) * count) / sizeof(task[0]) - 1);

or simply (suggested by Remy Lebeau):

TTask::WaitForAll(task, count - 1);
Tracer
  • 2,544
  • 2
  • 23
  • 58
  • **You don't need to use `sizeof` at all**. `(sizeof(task[0]) * count) / sizeof(task[0])` is the same value as `count`, so just use `count` by itself: `TTask::WaitForAll(task, count-1);` Or, you can use the `SLICE()` macro in ``: `TTask::WaitForAll(SLICE(task, count));` In the case when you used a static array, the `EXISTINGARRAY()` macro could have been used instead: `TTask::WaitForAll(EXISTINGARRAY(task));` See [Delphi Compatibility Macros](http://docwiki.embarcadero.com/RADStudio/en/Delphi_Compatibility_Macros) – Remy Lebeau Dec 02 '19 at 16:29