Skip to content

Commit

Permalink
WIP. Dict now uses class instead of struct in order to prevent copyin…
Browse files Browse the repository at this point in the history
…g slots two times. There is still a problem with GetEntry() using too many entries.
  • Loading branch information
nseam committed Jul 1, 2024
1 parent 2a805d1 commit e7ba4d5
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Dict.enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#pragma once
#endif

#define DICT_GROW_UP_PERCENT_DEFAULT 50
#define DICT_GROW_UP_PERCENT_DEFAULT 100
#define DICT_PERFORMANCE_PROBLEM_AVG_CONFLICTS 20

/**
Expand Down
22 changes: 19 additions & 3 deletions Dict.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class Dict : public DictBase<K, V> {
}

void Clear() {
_DictSlots_ref = new DictSlotsRef<K, V>();

for (unsigned int i = 0; i < (unsigned int)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots); ++i) {
if (THIS_ATTR _DictSlots_ref.DictSlots[i].IsUsed()) THIS_ATTR _DictSlots_ref.DictSlots[i].SetFlags(0);
}
Expand Down Expand Up @@ -210,7 +212,7 @@ class Dict : public DictBase<K, V> {
/**
* Inserts value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, const K key, V value, bool allow_resize) {
bool InsertInto(DictSlotsRef<K, V>*& dictSlotsRef, const K key, V value, bool allow_resize) {
if (THIS_ATTR _mode == DictModeUnknown)
THIS_ATTR _mode = DictModeDict;
else if (THIS_ATTR _mode != DictModeDict) {
Expand Down Expand Up @@ -315,7 +317,7 @@ class Dict : public DictBase<K, V> {
/**
* Inserts hashless value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, V value) {
bool InsertInto(DictSlotsRef<K, V>*& dictSlotsRef, V value) {
if (THIS_ATTR _mode == DictModeUnknown)
THIS_ATTR _mode = DictModeList;
else if (THIS_ATTR _mode != DictModeList) {
Expand Down Expand Up @@ -353,6 +355,18 @@ class Dict : public DictBase<K, V> {
MathMax(10, (int)((float)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f))));
}

public:
/**
* Ensures that there is at least given number of slots in dict.
*/
bool Reserve(int _size) {
if (_size <= ArraySize(THIS_ATTR _DictSlots_ref.DictSlots)) {
return true;
}
return Resize(_size);
}

protected:
/**
* Shrinks or expands array of DictSlots.
*/
Expand All @@ -362,7 +376,7 @@ class Dict : public DictBase<K, V> {
return true;
}

DictSlotsRef<K, V> new_DictSlots;
DictSlotsRef<K, V>* new_DictSlots = new DictSlotsRef<K, V>();

if (ArrayResize(new_DictSlots.DictSlots, new_size) == -1) return false;

Expand All @@ -389,6 +403,8 @@ class Dict : public DictBase<K, V> {
// Freeing old DictSlots array.
ArrayFree(THIS_ATTR _DictSlots_ref.DictSlots);

delete THIS_ATTR _DictSlots_ref;

THIS_ATTR _DictSlots_ref = new_DictSlots;

return true;
Expand Down
11 changes: 6 additions & 5 deletions DictBase.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ class DictBase {
_mode = DictModeUnknown;
_flags = 0;
overflow_listener = nullptr;
_DictSlots_ref = new DictSlotsRef<K, V>();
}

/**
* Destructor.
*/
~DictBase() {}
~DictBase() { delete _DictSlots_ref; }

DictIteratorBase<K, V> Begin() {
// Searching for first item index.
Expand Down Expand Up @@ -106,7 +107,7 @@ class DictBase {
/**
* Returns slot by key.
*/
DictSlot<K, V>* GetSlotByKey(DictSlotsRef<K, V>& dictSlotsRef, const K _key, unsigned int& position) {
DictSlot<K, V>* GetSlotByKey(DictSlotsRef<K, V>*& dictSlotsRef, const K _key, unsigned int& position) {
unsigned int numSlots = ArraySize(dictSlotsRef.DictSlots);

if (numSlots == 0) return NULL;
Expand Down Expand Up @@ -137,7 +138,7 @@ class DictBase {
/**
* Returns slot by position.
*/
DictSlot<K, V>* GetSlotByPos(DictSlotsRef<K, V>& dictSlotsRef, const unsigned int position) {
DictSlot<K, V>* GetSlotByPos(DictSlotsRef<K, V>*& dictSlotsRef, const unsigned int position) {
return dictSlotsRef.DictSlots[position].IsUsed() ? &dictSlotsRef.DictSlots[position] : NULL;
}

Expand Down Expand Up @@ -335,9 +336,9 @@ class DictBase {

protected:
/**
* Array of DictSlots.
* Pointer to array of DictSlots.
*/
DictSlotsRef<K, V> _DictSlots_ref;
DictSlotsRef<K, V>* _DictSlots_ref;

DictOverflowListener overflow_listener;
unsigned int overflow_listener_max_conflicts;
Expand Down
28 changes: 22 additions & 6 deletions DictObject.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
*/

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
// Allows the preprocessor to include a header file when it is needed.
#pragma once
#endif

#include "Convert.basic.h"
Expand Down Expand Up @@ -105,6 +105,8 @@ class DictObject : public DictBase<K, V> {
}

void Clear() {
_DictSlots_ref = new DictSlotsRef<K, V>();

for (unsigned int i = 0; i < (unsigned int)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots); ++i) {
this PTR_DEREF _DictSlots_ref.DictSlots[i].SetFlags(0);
}
Expand Down Expand Up @@ -210,7 +212,7 @@ class DictObject : public DictBase<K, V> {
/**
* Inserts value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, const K key, V& value, bool allow_resize) {
bool InsertInto(DictSlotsRef<K, V>*& dictSlotsRef, const K key, V& value, bool allow_resize) {
if (THIS_ATTR _mode == DictModeUnknown)
THIS_ATTR _mode = DictModeDict;
else if (THIS_ATTR _mode != DictModeDict) {
Expand Down Expand Up @@ -315,7 +317,7 @@ class DictObject : public DictBase<K, V> {
/**
* Inserts hashless value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, V& value) {
bool InsertInto(DictSlotsRef<K, V>*& dictSlotsRef, V& value) {
if (this PTR_DEREF _mode == DictModeUnknown)
this PTR_DEREF _mode = DictModeList;
else if (this PTR_DEREF _mode != DictModeList) {
Expand Down Expand Up @@ -354,6 +356,18 @@ class DictObject : public DictBase<K, V> {
10, (int)((float)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f))));
}

public:
/**
* Ensures that there is at least given number of slots in dict.
*/
bool Reserve(int _size) {
if (_size <= ArraySize(THIS_ATTR _DictSlots_ref.DictSlots)) {
return true;
}
return Resize(_size);
}

protected:
/**
* Shrinks or expands array of DictSlots.
*/
Expand All @@ -364,7 +378,7 @@ class DictObject : public DictBase<K, V> {
return true;
}

DictSlotsRef<K, V> new_DictSlots;
DictSlotsRef<K, V>* new_DictSlots = new DictSlotsRef<K, V>();

int i;

Expand All @@ -389,7 +403,9 @@ class DictObject : public DictBase<K, V> {
// Freeing old DictSlots array.
ArrayFree(this PTR_DEREF _DictSlots_ref.DictSlots);

this PTR_DEREF _DictSlots_ref = new_DictSlots;
delete THIS_ATTR _DictSlots_ref;

THIS_ATTR _DictSlots_ref = new_DictSlots;

return true;
}
Expand Down
20 changes: 10 additions & 10 deletions DictSlotsRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
*/

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
// Allows the preprocessor to include a header file when it is needed.
#pragma once
#endif

// Includes.
Expand All @@ -42,7 +42,8 @@ template <typename K, typename V>
class DictSlot;

template <typename K, typename V>
struct DictSlotsRef {
class DictSlotsRef {
public:
ARRAY(DictSlot<K _COMMA V>, DictSlots);

// Incremental index for dict operating in list mode.
Expand All @@ -61,14 +62,13 @@ struct DictSlotsRef {
_avg_conflicts = 0;
}

void operator=(DictSlotsRef& r) {
Util::ArrayCopy(DictSlots, r.DictSlots);
_list_index = r._list_index;
_num_used = r._num_used;
_num_conflicts = r._num_conflicts;
_avg_conflicts = r._avg_conflicts;
}
private:
/**
* Private assignment operator to avoid invalid copying.
*/
void operator=(DictSlotsRef& r) {}

public:
/**
* Adds given number of conflicts for an insert action, so we can store average number of conflicts.
*/
Expand Down
25 changes: 21 additions & 4 deletions DictStruct.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class DictStruct : public DictBase<K, V> {
}

void Clear() {
delete _DictSlots_ref;
_DictSlots_ref = new DictSlotsRef<K, V>();

for (unsigned int i = 0; i < (unsigned int)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots); ++i) {
THIS_ATTR _DictSlots_ref.DictSlots[i].SetFlags(0);
}
Expand Down Expand Up @@ -256,7 +259,7 @@ class DictStruct : public DictBase<K, V> {
/**
* Inserts value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, const K key, V& value, bool allow_resize) {
bool InsertInto(DictSlotsRef<K, V>*& dictSlotsRef, const K key, V& value, bool allow_resize) {
if (THIS_ATTR _mode == DictModeUnknown)
THIS_ATTR _mode = DictModeDict;
else if (THIS_ATTR _mode != DictModeDict) {
Expand Down Expand Up @@ -361,7 +364,7 @@ class DictStruct : public DictBase<K, V> {
/**
* Inserts hashless value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, V& value) {
bool InsertInto(DictSlotsRef<K, V>*& dictSlotsRef, V& value) {
if (THIS_ATTR _mode == DictModeUnknown)
THIS_ATTR _mode = DictModeList;
else if (THIS_ATTR _mode != DictModeList) {
Expand Down Expand Up @@ -398,6 +401,18 @@ class DictStruct : public DictBase<K, V> {
MathMax(10, (int)((float)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f))));
}

public:
/**
* Ensures that there is at least given number of slots in dict.
*/
bool Reserve(int _size) {
if (_size <= ArraySize(THIS_ATTR _DictSlots_ref.DictSlots)) {
return true;
}
return Resize(_size);
}

protected:
/**
* Shrinks or expands array of DictSlots.
*/
Expand All @@ -407,7 +422,7 @@ class DictStruct : public DictBase<K, V> {
return true;
}

DictSlotsRef<K, V> new_DictSlots;
DictSlotsRef<K, V>* new_DictSlots = new DictSlotsRef<K, V>();

if (ArrayResize(new_DictSlots.DictSlots, new_size) == -1) {
return false;
Expand All @@ -432,7 +447,9 @@ class DictStruct : public DictBase<K, V> {
}
}
// Freeing old DictSlots array.
ArrayFree(THIS_ATTR _DictSlots_ref.DictSlots);
ArrayFree(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots);

delete THIS_ATTR _DictSlots_ref;

THIS_ATTR _DictSlots_ref = new_DictSlots;

Expand Down
10 changes: 7 additions & 3 deletions Indicator/IndicatorCandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ class IndicatorCandle : public Indicator<TS> {
*/
IndicatorCandle(const TS& _icparams, const IndicatorDataParams& _idparams, IndicatorData* _indi_src = NULL,
int _indi_mode = 0)
: Indicator<TS>(_icparams, _idparams, _indi_src, _indi_mode), history(INDI_CANDLE_HISTORY_SIZE) {
: Indicator<TS>(_icparams, _idparams, _indi_src, _indi_mode), history(THIS_PTR, INDI_CANDLE_HISTORY_SIZE) {
Init();
}
IndicatorCandle(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, int _shift = 0, string _name = "")
: Indicator<TS>(_itype, _shift, _name), history(INDI_CANDLE_HISTORY_SIZE) {
: Indicator<TS>(_itype, _shift, _name), history(THIS_PTR, INDI_CANDLE_HISTORY_SIZE) {
Init();
}

Expand Down Expand Up @@ -361,7 +361,11 @@ class IndicatorCandle : public Indicator<TS> {
* because otherwise, we could end up with OnCalculate() working on partial
* history candles.
*/
void OnDataSourceWillEmitEntries(ENUM_INDI_EMITTED_ENTRY_TYPE _type, int _num_entries) override {}
void OnDataSourceWillEmitEntries(ENUM_INDI_EMITTED_ENTRY_TYPE _type, int _num_entries) override {
if (_type == INDI_EMITTED_ENTRY_TYPE_CANDLE) {
idata.Reserve(_num_entries);
}
}

/**
* Returns value storage of given kind.
Expand Down
2 changes: 1 addition & 1 deletion Indicator/IndicatorCandle.provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#include "../Storage/ItemsHistory.h"

/**
* Regenerates candles and updates exising candles from new ticks. Subclasses by IndicatorTf, IndicatorRenko.
* Regenerates candles and updates exising candles from new ticks. Subclassed by IndicatorTf, IndicatorRenko.
*/
template <typename TV>
class ItemsHistoryCandleProvider : public ItemsHistoryItemProvider<CandleOCTOHLC<TV>> {
Expand Down
8 changes: 4 additions & 4 deletions Indicator/IndicatorTick.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#define INDICATOR_TICK_H

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
// Allows the preprocessor to include a header file when it is needed.
#pragma once
#endif

// Includes.
Expand Down Expand Up @@ -83,7 +83,7 @@ class IndicatorTick : public Indicator<TS> {
*/
IndicatorTick(string _symbol, const TS& _itparams, const IndicatorDataParams& _idparams,
IndicatorData* _indi_src = NULL, int _indi_mode = 0)
: Indicator<TS>(_itparams, _idparams, _indi_src, _indi_mode) {
: Indicator<TS>(_itparams, _idparams, _indi_src, _indi_mode), history(THIS_PTR) {
itparams = _itparams;
if (_indi_src != NULL) {
THIS_ATTR SetDataSource(_indi_src, _indi_mode);
Expand All @@ -92,7 +92,7 @@ class IndicatorTick : public Indicator<TS> {
Init();
}
IndicatorTick(string _symbol, ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, int _shift = 0, string _name = "")
: Indicator<TS>(_itype, _shift, _name) {
: Indicator<TS>(_itype, _shift, _name), history(THIS_PTR) {
symbol = _symbol;
Init();
}
Expand Down
4 changes: 4 additions & 0 deletions Indicators/Tf/Indi_TfMt.provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ class ItemsHistoryTfMtCandleProvider : public ItemsHistoryCandleProvider<TV> {
int _num_copied = CopyRates(indi PTR_DEREF GetSymbol(), indi PTR_DEREF GetTf(), _end_shift, _count, _rates);
ArrayResize(_out_arr, _num_copied);

// Acknowledging indicator that we will emit _num_copied number of candles.
_history PTR_DEREF GetIndicator()
PTR_DEREF OnDataSourceWillEmitEntries(INDI_EMITTED_ENTRY_TYPE_CANDLE, _num_copied);

for (int i = 0; i < _num_copied; ++i) {
MqlRates _rate = _rates[i];
int _start_secs = (int)(long)_rate.time;
Expand Down
Loading

0 comments on commit e7ba4d5

Please sign in to comment.