mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-31 14:45:14 +00:00
up to 64 realtime combinated interfaces
This commit is contained in:
@@ -20,6 +20,159 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class Interfaces;
|
||||
typedef void(*InterfaceConstruct)(void *location, Interfaces *interfaces);
|
||||
typedef void(*InterfaceDestruct)(void *location);
|
||||
|
||||
struct InterfaceWrapStruct {
|
||||
int Size;
|
||||
InterfaceConstruct Construct;
|
||||
InterfaceDestruct Destruct;
|
||||
};
|
||||
|
||||
template <int Value, int Denominator>
|
||||
struct CeilDivideMinimumOne {
|
||||
static const int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0));
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct InterfaceWrapTemplate {
|
||||
static const int Size = CeilDivideMinimumOne<sizeof(Type), sizeof(uint64)>::Result * sizeof(uint64);
|
||||
static void Construct(void *location, Interfaces *interfaces) {
|
||||
(new (location) Type())->interfaces = interfaces;
|
||||
}
|
||||
static void Destruct(void *location) {
|
||||
((Type*)location)->~Type();
|
||||
}
|
||||
};
|
||||
|
||||
extern InterfaceWrapStruct InterfaceWraps[64];
|
||||
extern QAtomicInt InterfaceIndexLast;
|
||||
|
||||
template <typename Type>
|
||||
class BasicInterface {
|
||||
public:
|
||||
static int Index() {
|
||||
static QAtomicInt _index(0);
|
||||
if (int index = _index.loadAcquire()) {
|
||||
return index - 1;
|
||||
}
|
||||
while (true) {
|
||||
int last = InterfaceIndexLast.loadAcquire();
|
||||
if (InterfaceIndexLast.testAndSetOrdered(last, last + 1)) {
|
||||
t_assert(last < 64);
|
||||
if (_index.testAndSetOrdered(0, last + 1)) {
|
||||
InterfaceWraps[last] = { InterfaceWrapTemplate<Type>::Size, InterfaceWrapTemplate<Type>::Construct, InterfaceWrapTemplate<Type>::Destruct };
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return _index.loadAcquire() - 1;
|
||||
}
|
||||
static const uint64 Bit() {
|
||||
return (1 << Index());
|
||||
}
|
||||
Interfaces *interfaces = 0;
|
||||
};
|
||||
|
||||
class InterfacesMetadata {
|
||||
public:
|
||||
|
||||
InterfacesMetadata(uint64 mask) : _mask(mask), size(0), last(64) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
uint64 m = (1 << i);
|
||||
if (_mask & m) {
|
||||
int s = InterfaceWraps[i].Size;
|
||||
if (s) {
|
||||
offsets[i] = size;
|
||||
size += s;
|
||||
} else {
|
||||
offsets[i] = -1;
|
||||
}
|
||||
} else if (_mask < m) {
|
||||
last = i;
|
||||
for (; i < 64; ++i) {
|
||||
offsets[i] = -1;
|
||||
}
|
||||
} else {
|
||||
offsets[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size, last;
|
||||
int offsets[64];
|
||||
|
||||
private:
|
||||
uint64 _mask;
|
||||
|
||||
};
|
||||
|
||||
const InterfacesMetadata *GetInterfacesMetadata(uint64 mask);
|
||||
|
||||
class Interfaces {
|
||||
public:
|
||||
|
||||
Interfaces(uint64 mask = 0) : _meta(GetInterfacesMetadata(mask)), _data(0) {
|
||||
if (_meta->size) {
|
||||
_data = malloc(_meta->size);
|
||||
if (!_data) { // terminate if we can't allocate memory
|
||||
throw "Can't allocate memory!";
|
||||
}
|
||||
|
||||
for (int i = 0; i < _meta->last; ++i) {
|
||||
int offset = _meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
try {
|
||||
InterfaceWraps[i].Construct(_dataptrunsafe(offset), this);
|
||||
} catch (...) {
|
||||
while (i > 0) {
|
||||
--i;
|
||||
offset = _meta->offsets[--i];
|
||||
if (offset >= 0) {
|
||||
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
~Interfaces() {
|
||||
if (_data) {
|
||||
for (int i = 0; i < _meta->last; ++i) {
|
||||
int offset = _meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
|
||||
}
|
||||
}
|
||||
free(_data);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Type *Get() {
|
||||
return (Type*)_dataptr(_meta->offsets[Type::Index()]);
|
||||
}
|
||||
template <typename Type>
|
||||
const Type *Get() const {
|
||||
return (const Type*)_dataptr(_meta->offsets[Type::Index()]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void *_dataptrunsafe(int skip) const {
|
||||
return (char*)_data + skip;
|
||||
}
|
||||
void *_dataptr(int skip) const {
|
||||
return (skip >= 0) ? _dataptrunsafe(skip) : 0;
|
||||
}
|
||||
const InterfacesMetadata *_meta;
|
||||
void *_data;
|
||||
|
||||
};
|
||||
|
||||
typedef int32 ChannelId;
|
||||
static const ChannelId NoChannel = 0;
|
||||
|
||||
|
Reference in New Issue
Block a user