TokenSpace: fix token wraparound

Fix bug that allocating/freeing a lot of BHandler cause token wraparound
and overwriting existing assigned tokens.

Change-Id: I12527126644bca1793a8475dc487f131e6f83437
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9533
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
X512
2025-08-03 22:50:25 +00:00
committed by waddlesplash
parent 00c891c0c8
commit 2a70c45937
2 changed files with 27 additions and 10 deletions
+1 -1
View File
@@ -62,7 +62,7 @@ private:
typedef std::map<int32, token_info> TokenMap; typedef std::map<int32, token_info> TokenMap;
TokenMap fTokenMap; TokenMap fTokenMap;
int32 fTokenCount; int32 fNextToken;
}; };
+26 -9
View File
@@ -20,10 +20,20 @@ BTokenSpace gDefaultTokens;
// the default token space - all handlers will go into that one // the default token space - all handlers will go into that one
static int32
get_next_token(int32 token)
{
if (token == INT32_MAX)
return 1;
else
return token + 1;
}
BTokenSpace::BTokenSpace() BTokenSpace::BTokenSpace()
: :
BLocker("token space"), BLocker("token space"),
fTokenCount(1) fNextToken(1)
{ {
} }
@@ -39,17 +49,24 @@ BTokenSpace::NewToken(int16 type, void* object)
BAutolock locker(this); BAutolock locker(this);
token_info tokenInfo = { type, object, NULL }; token_info tokenInfo = { type, object, NULL };
int32 token = fTokenCount;
int32 wraparoundToken = fNextToken;
try { try {
fTokenMap[token] = tokenInfo; for (;;) {
int32 token = fNextToken;
bool done = fTokenMap.insert(std::pair(token, tokenInfo)).second;
fNextToken = get_next_token(token);
if (done)
return token;
if (fNextToken == wraparoundToken)
return -1;
}
} catch (std::bad_alloc& exception) { } catch (std::bad_alloc& exception) {
return -1; return -1;
} }
fTokenCount++;
return token;
} }
@@ -73,8 +90,8 @@ BTokenSpace::SetToken(int32 token, int16 type, void* object)
} }
// this makes sure SetToken() plays more or less nice with NewToken() // this makes sure SetToken() plays more or less nice with NewToken()
if (token >= fTokenCount) if (token >= fNextToken)
fTokenCount = token + 1; fNextToken = get_next_token(token);
return true; return true;
} }