in Extremem/src/main/java/com/amazon/corretto/benchmark/extremem/ServerThread.java [95:235]
public void runExtreme() {
while (true) {
// If the simulation will have ended before we wake up, don't
// even bother to sleep.
if (next_release_time.compare(end_simulation_time) >= 0)
break;
AbsoluteTime now = next_release_time.sleep(this);
now.garbageFootprint(this);
// In an earlier implementation, termination of the thread was
// determined by comparing next_release_time against
// end_simulation_time. In the case that the thread falls
// hopelessly behind schedule, the thread "never" terminates.
if (now.compare(end_simulation_time) >= 0)
break;
Trace.msg(4, "Server ", label, ": attention: ",
Integer.toString(attention));
switch (attention) {
case 0:
// Statistically, the number of pending SalesTransaction
// instances that accumulate on my sales_queue since the
// last time I serviced this queue should be approximately
// constant. The greatest source of variance would be
// contention with other server threads that might be
// servicing the same queue.
int transaction_count = 0;
while (true) {
SalesTransaction x = sales_queue.dequeue();
if (x != null) {
transaction_count++;
// Note that either the customer or the product may be
// decommissioned prior to transaction of the sale. Our
// simple implementation of transaction is not harmed by
// either. In the case that either of these entities is
// decommissioned while transaction is pending, the
// SalesTransaction object will force the entity to
// remain alive until the transaction is performed.
// Thereafter, the decommissioned object will be
// eligible for garbage collection. To simplify
// bookkeeping, we account that the object has become
// garbage at the moment it is decommissioned, even
// though the garbage collector may have to wait for the
// sale to be transacted before reclaiming it.
Customer c = x.customer();
c.transactSale(this, next_release_time, x);
x.garbageFootprint(this);
} else
break;
}
Trace.msg(4, "Server ", label, ": processed sales transactions: ",
Integer.toString(transaction_count));
history.logTransactions(this, next_release_time, transaction_count);
break;
case 1:
// Statistically, the number of BrowsingHistory instances that
// expire since the last time I serviced this queue should
// be approximately constant. The greatest source of
// variance would be contention with other server threads
// that might be servicing the same queue.
int browsing_expirations = 0;
while (true) {
BrowsingHistory h;
h = browsing_queue.pullIfExpired(next_release_time);
if (h != null) {
browsing_expirations++;
Customer c = h.customer();
c.retireOneSaveForLater(h);
h.garbageFootprint(this);
} else
break;
}
Trace.msg(4, "Server ", label, ": browsing_expirations: ",
Integer.toString(browsing_expirations));
history.logHistories(this, next_release_time, browsing_expirations);
break;
case 2:
if (next_release_time.compare(customer_replacement_time) >= 0) {
for (int i = config.CustomerReplacementCount(); i > 0; i--)
all_customers.replaceRandomCustomer(this);
customer_replacement_time.garbageFootprint(this);
customer_replacement_time = (
customer_replacement_time
.addRelative(this, config.CustomerReplacementPeriod()));
customer_replacement_time.changeLifeSpan(this,
LifeSpan.TransientShort);
Trace.msg(4, "Server ", label, ": replaced ",
Integer.toString(config.CustomerReplacementCount()),
" customers");
history.logCustomers(this, next_release_time,
config.CustomerReplacementCount());
} else {
Trace.msg(4, "Server ", label, ": too early to replace customers");
history.logDoNothings(this, next_release_time);
}
break;
case 3:
assert (3 + 1 == TotalAttentionPoints): "Bad TotalAttentionPoints";
if (next_release_time.compare(product_replacement_time) >= 0) {
for (int i = config.ProductReplacementCount(); i > 0; i--)
all_products.replaceRandomProduct(this);
product_replacement_time.garbageFootprint(this);
product_replacement_time = (
product_replacement_time
.addRelative(this, config.ProductReplacementPeriod()));
product_replacement_time.changeLifeSpan(this,
LifeSpan.TransientShort);
Trace.msg(4, "Server ", label, ": replaced products: ",
Integer.toString(config.ProductReplacementCount()));
history.logProducts(this, next_release_time,
config.ProductReplacementCount());
} else {
Trace.msg(4, "Server ", label, ": too early to replace products");
history.logDoNothings(this, next_release_time);
}
break;
default:
assert (false): " Unhandled attention point in server thread";
}
if (attention-- == 0)
attention = TotalAttentionPoints - 1;
next_release_time.garbageFootprint(this);
next_release_time = (
next_release_time.addRelative(this, config.ServerPeriod()));
next_release_time.changeLifeSpan(this, LifeSpan.TransientShort);
}
Trace.msg(2, "Server ", label, " terminating. Time is up.");
// We accumulate accumulator even if reporting individual threads
accumulator.accumulate(history);
if (config.ReportIndividualThreads())
this.report(this);
else {
alloc_accumulator.foldInto(memoryLog());
garbage_accumulator.foldInto(garbageLog());
}
}