how to restart coroutine on event?

I have a non-MonoBehavior class with some background functions that are supposed to wait for some time, then make a minor operation. A single component has several instances of that class, so I can’t call invokeRepeating from the component (cannot access the individual instances’ functions) nor the class itself (not a MonoBehaviour). Coroutines seem to be the most appropriate.
However, I need to be able to ‘restart’ the coroutine on a specific event, i.e. reset its delays. Any hints on how to do this from the outside or passively? Or can I only do this by explicitly checking the state every Update cycle?

In specific, my objects have several layers of health. Each layer can regenerate a full point of health every few seconds but if a layer receives damage, it looses the progress on regenerating the current new health point and must wait for a penalty delay before beginning the regeneration process anew.

// start after receiving damage
function regenerate () {
	// wait for damage penalty being done xor cancel and restart when receiving damage
	yield WaitForSeconds(attributes.regenDamageDelay); // <- need hook here
	while (true) {
		// wait a cycle xor cancel and restart when receiving damage
		yield WaitForSeconds(attributes.regenSecondsPerTick); // <- need hook here
		currentHealth++;
	}
}

If I understand you correctly you want to be able to break the cycle at any point. Using a condition for when the part receives damage and current elapsed time will let you do this. Set a boolean variable to true (called receivedDamage in example) when the part is taking damage, then yield one frame before you call Regenerate().

private var receivedDamage : boolean = false;
    
function Regenerate () {

    receivedDamage = false;

    //Do a time stamp
    var t : float = Time.time;

    //Use the time stamp as a condition
    while (Time.time<t+attributes.regenDamageDelay) {
        //Use another condition for when receiving damage to exit loop
        if (receivedDamage) return;
        yield;
    }

    //Set the condition to repeat while currentHealth is less than maxHealth and doesn't receive damage
    while (!receivedDamage && currentHealth<maxHealth) {

        //Do another time stamp
        t = Time.time;

        while (Time.time<t+attributes.regenSecondsPerTick) {
            if (receivedDamage) return;
            yield;
        }

        currentHealth++;
        yield;
    }
}

Okay, I got this working now with a mixture of the two: a coroutine carrying a timestamp of its own invocation and the parent class carrying a timestamp of the last invocation of its coroutine.

When the function gets invoked, it will set both the class timestamp and its own timestamp to be the same. Before each action, it will check whether the two are identical, i.e. if in the meantime another one was invoked. For robustness, the timestamp doesn’t store the actual time but the order of invocation.
The stamp is big enough for 1000 invocations every second for about 1.5 months…

class healthTest {
	var id : String;
	var health : int;
	var invokeStamp : uint;
	var timeInitial : float = 1;
	var timeRepeat : float = 2;
	
	function classCoroutine ( ) {
		invokeStamp++;	// store in the class when last this routine was invoked
		var initStamp : uint = invokeStamp;	// store in the routine when this specific routine instance was invoked
		Debug.Log('started coroutine');
		yield WaitForSeconds(timeInitial);
		if (invokeStamp!=initStamp) return;  // <- exit when not most current coroutine
		Debug.Log('finished initial delay @ ' + health + ' for ' + id);
		while ( true ) {
			yield WaitForSeconds(timeRepeat);
			if (invokeStamp!=initStamp) return;  // <- exit when not most current coroutine
			health++;	// <- do stuff when still alive
			Debug.Log('finished repeat delay @ ' + health + ' for ' + id);
		}
	}
}

Note that this specific example is bound to a parent class. The example class is not derived from MonoBehaviour so it cannot invoke the coroutine, this is done by the parent class.

// testComponent.js
var regenDummy1 : healthTest;
var regenDummy2 : healthTest;

function Start () {
    regenDummy1.id='regenDummy1';
    regenDummy2.id='regenDummy2';
    regenDummy2.timeRepeat*=2;
	StartCoroutine(regenDummy1.classCoroutine());
	StartCoroutine(regenDummy2.classCoroutine());
}

function OnCollisionEnter(collision : Collision) {
	// 're'start the coroutines
	StartCoroutine(regenDummy1.classCoroutine());
	StartCoroutine(regenDummy2.classCoroutine());
}