use of org.eclipse.scout.rt.platform.exception.BeanCreationException in project scout.rt by eclipse.
the class DefaultBeanInstanceProducer method getApplicationScopedInstance.
private T getApplicationScopedInstance(final IBean<T> bean) {
T instance = m_applicationScopedInstance.get();
if (instance != null) {
return instance;
}
if (m_creatorThread.compareAndSet(null, Thread.currentThread())) {
try {
// check again to avoid race conditions
instance = m_applicationScopedInstance.get();
if (instance != null) {
return instance;
}
// current thread has to create instance
instance = safeCreateInstance(bean.getBeanClazz());
m_applicationScopedInstance.set(instance);
return instance;
} finally {
synchronized (this) {
// reset creator thread so that another one tries to create the bean again in case the current ran into an exception.
m_creatorThread.set(null);
// wake up other threads waiting on the application-scoped instance
this.notifyAll();
}
}
}
// remember creator thread for logging purposes
final Thread creatorThread = m_creatorThread.get();
final int maxWaitTimeSeconds = getDeadlockDetectionMaxWaitTimeSeconds();
final long maxWaitEndTimeMillis = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(maxWaitTimeSeconds);
boolean logDebug = LOG.isDebugEnabled();
do {
try {
synchronized (this) {
if (m_creatorThread.get() == null) {
break;
}
long waitTimeMillis = logDebug ? TimeUnit.SECONDS.toMillis(Math.min(maxWaitTimeSeconds, DEADLOCK_DETECTION_DEBUG_WAIT_TIME_SECONDS)) : maxWaitEndTimeMillis - System.currentTimeMillis();
if (waitTimeMillis > 0) {
// wait for the creator to complete, but not too long because the notify signal could have been missed
this.wait(waitTimeMillis);
}
}
} catch (InterruptedException e) {
throw new ThreadInterruptedError("Thread has been interrupted");
}
if (m_creatorThread.get() == null) {
break;
}
if (logDebug) {
logWarnPotentialDeadlock(creatorThread);
logDebug = false;
}
} while (// try as long as the other thread is still creating the bean and the max wait time has not been elapsed
System.currentTimeMillis() < maxWaitEndTimeMillis);
// check if bean has been created in the meantime
instance = m_applicationScopedInstance.get();
if (instance != null) {
return instance;
}
// bean has not been created
if (System.currentTimeMillis() < maxWaitEndTimeMillis) {
throw new BeanCreationException("Thread was waiting on bean instance creator thread which most likely failed (check the log).").withContextInfo("beanClass", bean == null || bean.getBeanClazz() == null ? "n/a" : bean.getBeanClazz().getName()).withContextInfo("creatorThreadID", creatorThread == null ? "n/a" : creatorThread.getId()).withContextInfo("creatorThreadName", creatorThread == null ? "n/a" : creatorThread.getName());
} else {
logWarnPotentialDeadlock(creatorThread);
throw new BeanCreationException("Potential deadlock detected: bean is being created by another thread. Either the creation takes longer than {}s " + "or the current and the creator threads are blocking each other (check the log).", maxWaitTimeSeconds).withContextInfo("beanClass", bean == null || bean.getBeanClazz() == null ? "n/a" : bean.getBeanClazz().getName()).withContextInfo("creatorThreadID", creatorThread == null ? "n/a" : creatorThread.getId()).withContextInfo("creatorThreadName", creatorThread == null ? "n/a" : creatorThread.getName());
}
}
Aggregations